eventListener를 추가하려면 다음 코드가 있습니다.
area.addEventListener('click',function(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
},true);
예상대로 올바르게 작동합니다. 나중에 다른 함수에서 다음 코드를 사용하여 이벤트 리스너를 제거하려고했습니다.
area.removeEventListener('click',function(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
},true);
하지만 짝수 리스너가 제거되지 않았습니다. 왜 발생합니까? 내 removeEventListener ()에 문제가 있습니까? 참고 : 여기에 document.getElementById ( ‘myId’)와 같은 영역이 있습니다.
답변
두 개의 익명 함수가 완전히 다른 함수이기 때문입니다. 귀하 removeEventListener
의 인수는 이전에 부착 된 함수 객체에 대한 참조하지 않습니다.
function foo(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
}
area.addEventListener('click',foo,true);
area.removeEventListener('click',foo,true);
답변
Windows 개체의 경우 마지막 매개 변수 “true”가 필요합니다. 캡처 플래그가 없으면 제거가 작동하지 않습니다.
답변
두 호출 모두에서 두 가지 다른 함수를 만들고 있습니다. 따라서 두 번째 기능은 첫 번째 기능과 어떤 식 으로든 관련이 없으며 엔진은 기능을 제거 할 수 있습니다. 대신 함수에 대한 공통 식별자를 사용하십시오.
var handler = function(event) {
app.addSpot(event.clientX,event.clientY);
app.addFlag = 1;
};
area.addEventListener('click', handler,true);
나중에 다음을 호출하여 핸들러를 제거 할 수 있습니다.
area.removeEventListener('click', handler,true);
답변
제거하려면 함수를 변수에 저장하거나 이름이 지정된 함수를 사용하고 해당 함수를 removeEventListener
호출에 전달 하십시오.
function areaClicked(event) {
app.addSpot(event.clientX, event.clientY);
app.addFlag = 1;
}
area.addEventListener('click', areaClicked, true);
// ...
area.removeEventListener('click', areaClicked, true);
답변
이벤트 리스너가 호출하는 함수에 지역 변수를 전달하려면 함수 내부에 함수를 정의하고 (지역 변수를 가져 오기 위해) 함수 자체에 함수 이름을 전달할 수 있습니다. 예를 들어 app을 로컬 변수로 사용하여 이벤트 리스너를 추가하는 함수 내에서 시작해 보겠습니다. 이 함수 안에 다음과 같은 함수를 작성합니다.
function yourFunction () {
var app;
function waitListen () {
waitExecute(app, waitListen);
}
area.addEventListener('click', waitListen, true);
}
그런 다음 waitExecute가 호출 될 때 제거해야하는 것이 있습니다.
function waitExecute (app, waitListen) {
... // other code
area.removeEventListener('click', waitListen, true);
}
답변
먼저 이벤트 핸들러를 정의하고
그리고
area.addEventListener('click',handler);
area.removeEventListener('click',handler);
답변
설명이 필요한 removeEventListener () 문제가 발생했습니다.
이벤트 리스너에 매개 변수를 전달할 수 있기를 원했기 때문에 이벤트 리스너를 생성하는 함수를 작성했습니다. 그러면 의도 한 이벤트 리스너를 콜백으로 호출하는 두 번째 함수가 반환됩니다.
전체 라이브러리 파일은 다음과 같습니다.
//Event handler constants
function EventHandlerConstants()
{
this.SUCCESS = 0; //Signals success of an event handler function
this.NOTFUNCTION = 1; //actualHandler argument passed to MakeEventHandler() is not a Function object
//End constructor
}
//MakeEventHandler()
//Arguments:
//actualHandler : reference to the actual function to be called as the true event handler
//selfObject : reference to whatever object is intended to be referenced via the "this" keyword within
// the true event handler. Set to NULL if no such object is needed by your true
// event handler specified in the actualHandler argument above.
//args : array containing the arguments to be passed to the true event handler, so that the true
// event handler can be written with named arguments, such as:
// myEventHandler(event, arg1, arg2, ... )
// If your function doesn't need any arguments, pass an empty array, namely [], as the
// value of this argument.
//Usage:
//c = new EventHandlerConstants();
//res = MakeEventHandler(actualHandler, selfObject, args);
//if (res == c.SUCCESS)
// element.addEventListener(eventType, res.actualHandler, true); //or whatever
function MakeEventHandler(actualHandler, selfObject, args)
{
var c = new EventHandlerConstants();
var funcReturn = null; //This will contain a reference to the actual function generated and passed back to
//the caller
var res = {
"status" : c.SUCCESS,
"actualHandler" : null
};
if (IsGenuineObject(actualHandler, Function))
{
res.actualHandler = function(event) {
var trueArgs = [event].concat(args);
actualHandler.apply(selfObject, trueArgs);
};
}
else
{
res.status = c.NOTFUNCTION;
//End if/else
}
//Return our result object with appropriate properties set ...
return(res);
//End function
}
그런 다음 이것이 의도 한대로 작동하는지 알아보기 위해 빠른 테스트 페이지를 작성하고 원하는대로 이벤트 처리기를 추가하고 제거 할 수 있도록했습니다.
HTML 테스트 페이지는 다음과 같습니다.
<!DOCTYPE html>
<html>
<head>
<!-- CSS goes here -->
<link rel="stylesheet" type="text/css" href="NewEventTest.css">
<!-- Required JavaScript library files -->
<script language = "JavaScript" src="BasicSupport.js"></script>
<script language = "JavaScript" src="EventHandler6.js"></script>
</head>
<body class="StdC" id="MainApplication">
<button type="button" class="StdC NoSwipe" id="Button1">Try Me Out</button>
<button type="button" class="StdC NoSwipe" id="Button2">Alter The 1st Button</button>
</body>
<script language = "JavaScript" src="NewEventTest.js"></script>
</html>
완전성을 위해 다음과 같은 간단한 CSS 파일도 사용합니다.
/* NewEventTest.css */
/* Define standard display settings classes for a range of HTML elements */
.StdC {
color: rgba(255, 255, 255, 1);
background-color: rgba(0, 128, 0, 1);
font-family: "Book Antiqua", "Times New Roman", "Times", serif;
font-size: 100%;
font-weight: normal;
text-align: center;
}
.NoSwipe {
user-select: none; /* Stops text from being selectable! */
}
테스트 코드는 다음과 같습니다.
//NewEventTest.js
function GlobalVariables()
{
this.TmpRef1 = null;
this.TmpRef2 = null;
this.TmpRef3 = null;
this.Const1 = null;
this.Handler1 = null;
this.Handler2 = null;
this.Handler3 = null;
this.EventOptions = {"passive" : true, "capture" : true };
//End constructor
}
//Button 1 Initial function
function Button1Initial(event)
{
console.log("Button 1 initial event handler triggered");
//End event handler
}
function Button1Final(event)
{
console.log("Button 1 final event handler triggered");
//End event handler
}
function Button2Handler(event, oldFunc, newFunc)
{
var funcRef = null;
this.removeEventListener("click", oldFunc);
this.addEventListener("click", newFunc, GLOBALS.EventOptions);
//End event handler
}
//Application Setup
GLOBALS = new GlobalVariables();
GLOBALS.Const1 = new EventHandlerConstants();
GLOBALS.TmpRef1 = document.getElementById("Button1");
GLOBALS.TmpRef2 = MakeEventHandler(Button1Initial, null, []);
if (GLOBALS.TmpRef2.status == GLOBALS.Const1.SUCCESS)
{
GLOBALS.Handler1 = GLOBALS.TmpRef2.actualHandler;
GLOBALS.TmpRef1.addEventListener("click", GLOBALS.Handler1, GLOBALS.EventOptions);
//End if
}
GLOBALS.TmpRef1 = MakeEventHandler(Button1Final, null, []);
if (GLOBALS.TmpRef1.status == GLOBALS.Const1.SUCCESS)
{
GLOBALS.Handler3 = GLOBALS.TmpRef1.actualHandler;
//End if
}
GLOBALS.TmpRef1 = document.getElementById("Button2");
GLOBALS.TmpRef2 = document.getElementById("Button1");
GLOBALS.TmpRef3 = Button1Final;
GLOBALS.TmpRef4 = MakeEventHandler(Button2Handler, GLOBALS.TmpRef2, [GLOBALS.Handler1, GLOBALS.Handler3]);
if (GLOBALS.TmpRef4.status == GLOBALS.Const1.SUCCESS)
{
GLOBALS.Handler2 = GLOBALS.TmpRef4.actualHandler;
GLOBALS.TmpRef1.addEventListener("click", GLOBALS.Handler2, GLOBALS.EventOptions);
//End if
}
따라서 수행 할 테스트는 다음과 같습니다.
[1] 클릭 이벤트 핸들러를 버튼 # 1에 연결합니다.
[2] 버튼을 클릭 할 때 이벤트 핸들러가 호출되는지 테스트합니다.
[3] 테스트가 통과되면 Button # 2를 클릭하고 그에 연결된 이벤트 핸들러를 호출합니다. 그러면 Button # 1에 연결된 이전 이벤트 핸들러가 제거되고 새 이벤트 핸들러로 대체됩니다.
단계 [1] 및 [2]는 정상적으로 작동합니다. 이벤트 핸들러가 첨부되고 버튼을 클릭 할 때마다 호출됩니다.
문제는 단계 [3]에 있습니다.
특히 단계 [3]에서 해당 이벤트 리스너를 제거하기 위해 MakeEventHandler ()에 의해 생성 된 함수에 대한 참조를 저장하더라도 removeEventListener ()를 호출해도 이벤트 리스너가 제거되지 않습니다. 이후에 Button # 1을 클릭하면 내가 제거한 것으로 추정되는 것을 포함하여 두 이벤트 리스너가 모두 실행됩니다!
말할 필요도없이이 동작은 모든 것을 신중하게 설정 했음에도 불구하고 내가 removeEventListener () 호출에서 지정한 함수가 처음에 addEventListener ()로 추가 한 자체 동일한 함수가되도록 설정 했음에도 불구하고 당황스러워 합니다. 주제에 대한 모든 문서에 따르면 ‘각 호출에 대해 동일한 기능에 대한 참조를 전달 (이 스레드 포함) 읽었 해야 작동하지만 명확하지 않습니다.
단계 [1]에서 예상대로 콘솔의 테스트 출력은 다음과 같습니다.
버튼 1 초기 이벤트 핸들러가 트리거 됨
코드는 예상대로 [2] 단계에서 실행되며 코드를 단계별로 추적하면 실제로 코드가 예상대로 실행됨을 알 수 있습니다.
그러나 단계 [3] 에서 버튼 # 1을 처음 클릭하면 원하는 결과를 얻을 수 있습니다.
버튼 1 최종 이벤트 핸들러가 트리거 됨
무슨 일이 버튼 # 1에 클릭 할 때 발생 이후 이 있습니다 :
버튼 1 초기 이벤트 핸들러가 트리거 됨 버튼 1 최종 이벤트 핸들러가 트리거 됨
확실히, 처음에 Button # 1에 연결된 함수가 클로저 내에서 생성 되었기 때문에 여전히 메모리에 유지 되더라도 요소에 대한 이벤트 리스너 컬렉션에서 분리되어야합니까? 왜 여전히 연결되어 있습니까?
또는 이벤트 리스너와 함께 클로저를 사용하는 것과 관련된 이상한 버그가 발생 했습니까?