Вопрос по javascript, events, addeventlistener – Javascript removeEventListener не работает

47

У меня есть следующий код для добавления eventListener

<code> area.addEventListener('click',function(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          },true);
</code>

Он работает правильно, как и ожидалось. Позже в другой функции я попытался удалить прослушиватель событий, используя следующий код

<code> area.removeEventListener('click',function(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          },true);
</code>

Но даже слушатель не удаляется .. Почему это происходит? Есть ли проблемы с моим removeEventListener ()? Примечание. Здесь область похожа на document.getElementById ("myId")

Ваш Ответ

7   ответов
1

true & quot; необходимо. Удаление не работает, если нет флага захвата.

Исправлена моя проблема. Благодарю.
1

сохраните функцию в переменной или просто используйте именованную функцию и передайте эту функциюremoveEventListener вызов:

function areaClicked(event) {
    app.addSpot(event.clientX, event.clientY);
    app.addFlag = 1;
}

area.addEventListener('click', areaClicked, true);
// ...
area.removeEventListener('click', areaClicked, true);
Это передано браузером. Не имеет значения, определяете ли вы функцию отдельно или нет.
но как я могу передать аргументы (здесь событие) этой функции .. Вот почему я использовал анонимную функцию Jinu Joseph Daniel
ВНИМАНИЕ: я узнал, что не так с моим подходом. Метод removeEventListener () работает ТОЛЬКО с ИМЕННЫМИ ФУНКЦИЯМИ. Это НЕ работает с анонимными функциями! Когда я отредактировал код, чтобы учесть это, все работало, как планировалось. Вы должны определить функцию NAMED в своем замыкании и вернуть ссылку на его экземпляр с параметрами, переданными закрытием. Сделайте это, и removeEventListener () работает отлично.
72

что две анонимные функции - это совершенно разные функции. ВашremoveEventListenerАргумент не является ссылкой на объект функции, который был ранее присоединен.

function foo(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          }
 area.addEventListener('click',foo,true);
 area.removeEventListener('click',foo,true);
Спасибо вам большое!
Это не позволит вам передавать параметры функции, напримерfoo(1)
Спасибоis not a reference to the function object that was previously attached
+1 верно.bind(this) поменяю подпись. Поэтому всегда назначайте функциюvar после связыванияthis для использования функцииbind API так что жеvar может быть использован вremoveListener, Вы увидите эту проблему более очевидной в машинописи
1

вызываемую прослушивателем событий, вы можете определить функцию внутри функции (чтобы получить локальные переменные) и передать имя функции в самой функции. Например, давайте начнем внутри функции, которая добавляет прослушиватель событий с приложением в качестве локальной переменной. Вы бы написали функцию внутри этой функции, такую как,

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);
}
Я столкнулся с проблемой здесь. Даже если вы определите функцию-обработчик события, сохраните ссылку на эту функцию, а затем передадите эту ссылку в removeEventListener () позже, функция не будет удалена. Комментарий слишком мал для размещения кода, поэтому, если вам нужен код, мне придется использовать поле для ответов ...
Дополнение к вышесказанному: еще одно интересное явление, которое я обнаружил, заключается в том, что даже если вы укажете, что ваш прослушиватель событий пассивен, старый все еще сохраняется в цепочке. Хуже того, старый теперь становится обработчиком блокирующих событий, а новый сохраняет свой пассивный статус. Я думаю, что здесь нужно объяснение.
0

а потом

area.addEventListener('click',handler);
area.removeEventListener('click',handler);
2

вторая функция никак не связана с первой, и двигатель может удалить эту функцию. Вместо этого используйте общий идентификатор для функции.

var handler = function(event) {
              app.addSpot(event.clientX,event.clientY);
              app.addFlag = 1;
          };
area.addEventListener('click', handler,true);

позже вы можете удалить обработчик, вызвав

area.removeEventListener('click', handler,true);
0

связанной с 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] После того, как этот тест пройден, нажмите кнопку № 2 и вызовите прикрепленный к нему обработчик событий, который удаляет старый обработчик событий, прикрепленный к кнопке № 1, а затем заменяет его новым обработчиком событий.

Шаги [1] и [2] работают нормально. Обработчик событий присоединяется и вызывается всякий раз, когда я нажимаю на кнопку.

Проблема с шагом [3].

Несмотря на то, что я сохраняю ссылку на функцию, сгенерированную MakeEventHandler (), специально для цели удаления этого прослушивателя событий в шаге [3], вызов removeEventListener () НЕ удаляет прослушиватель событий. Последующее нажатие на кнопку # 1 запускает ОБА слушателей событий, включая того, кого якобы удалил!

Излишне говорить, что это поведение я нахожу озадачивающим, несмотря на тщательную настройку, чтобы функция, указанная в вызове removeEventListener (), была той же самой функцией, которую я изначально добавил с помощью addEventListener () - согласноall документацию по теме, которую я прочитал (включая эту ветку), передавая ссылку на одну и ту же функцию для каждого вызоваshould работать, но явно не так.

На шаге [1] тестовый вывод в консоли читает, как и ожидалось:

Button 1 initial event handler triggered

Код также запускается, как и ожидалось, на шаге [2], и пошаговая трассировка кода показывает, что код выполняется действительно, как и ожидалось.

Но на этапе [3], в то время какfirst нажатие на кнопку # 1 дает желаемый результат:

Button 1 final event handler triggered

что происходит при нажатии кнопки №1subsequently это:

Button 1 initial event handler triggered Button 1 final event handler triggered

Конечно, даже если функция, изначально присоединенная к кнопке № 1, все еще сохраняется в памяти, поскольку она была сгенерирована в замыкании, она все равно должна быть отсоединена от коллекции прослушивателей событий для элемента? Почему это все еще связано?

Или я столкнулся с какой-то странной ошибкой, связанной с использованием замыканий со слушателями событий, о которых нужно сообщить?

Я столкнулся с этим также. Это ерунда. Пришлось прибегнуть к грязным способам обхода, т.е. отслеживание того, какие события должны быть включены / отключены в объекте окна.
Вы должны задать новый вопрос. Эта область отвечает на вопрос OP.

Похожие вопросы