addEventListener запускается несколько раз для одного и того же дескриптора при передаче аргументов с анонимной функцией

По какой-то причине прослушиватель событий запускается дважды для каждого элемента при передаче аргументов в анонимную функцию. Т.е. событие клика по элементу el будет регистрироваться один раз и, таким образом, стрелять один раз.

el.addEventListener("click", handle, false);
el.addEventListener("click", handle, false);

Но если я хочу передать свои собственные аргументы, он будет зарегистрирован и запущен дважды.

el.addEventListener("click", function() { handle(event, myArgument); }, false);
el.addEventListener("click", function() { handle(event, myArgument); }, false);

Вопрос в том, почему и в чем решение?

Я искал в другом месте и не могу найти решение или понять, почему эта проблема возникает. Я попытался реализовать решения в разделе Как передать аргумент функции слушателя, передаваемой в addEventListener? но они не помогли -

Я сделал базовую анонимную функцию или замыкание, а затем более продвинутую версию, которая показана ниже, но она сработала.

Я не понимаю, почему при отсутствии аргументов событие элемента регистрируется один раз, а при передаче аргументов событие элемента регистрируется дважды.

Вот код:

<html>
    <head>
        <script type="text/javascript">
            var handle_2 = function(evt, type) {
                var test;
                switch (type) {
                    case "focus": 
                        console.log(evt.target.value);
                        break;
                    case "click":
                        console.log(evt.target.id + " was clicked");
                        break;
                    default: console.log("no type found");
                }
            };

            window.onload = function() {
                var textbox = document.getElementById("t1");
                var button = document.getElementById("btn");
                textbox.value = "456";
                button.value = "Press";

                var typeFocus = "focus", typeClick = "click";

                textbox.addEventListener("focus", (function(typeFocus) { return function(evt) { handle_2(evt, typeFocus); }})(typeFocus), false);
                button.addEventListener("click", (function(typeClick) { return function(evt) { handle_2(evt, typeClick); }})(typeClick), false);

                // Registers again for each element. Why?
                textbox.addEventListener("focus", (function(typeFocus) { return function(evt) { handle_2(evt, typeFocus); }})(typeFocus), false);
                button.addEventListener("click", (function(typeClick) { return function(evt) { handle_2(evt, typeClick); }})(typeClick), false);
            };
        </script>
    </head>
    <body>
        <div id="wrapper">
            <input id="t1" type="text" />
            <input id="btn" type="button" />
        </div>
    </body>
</html>

Любая помощь будет оценена. Спасибо.

4 ответа

Решение

Самое простое решение - создать новый обработчик только один раз:

var newHandle = function(event) { handle(event, myArgument); };

el.addEventListener("click", newHandle, false);
el.addEventListener("click", newHandle, false);

Что ж,,

el.addEventListener("click", handle, false);
el.addEventListener("click", handle, false);

Регистрируется в той же функции "handle()"

el.addEventListener("click", function() { handle(event, myArgument); }, false);
el.addEventListener("click", function() { handle(event, myArgument); }, false);

Регистрирует "function() { handle(event, myArgument)"... которые являются двумя уникальными анонимными функциями. Таким образом, он будет стрелять дважды.

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

el.addEventListener("click", crateHandle(myArgument), false);

var createHandle = function(myArgument) {
  return function(event) {
    .... do something
  };
}

Это все еще не решает проблему огня дважды все же.

addEventListener регистрирует столько слушателей, сколько он использует.

Согласно документации, требуется 3 аргумента, третий useCapture который не имеет никакого отношения к регистрации слушателя дважды или нет. По умолчанию установлено falseтак что добавляя false в качестве третьего параметра мало что меняет.

       useEffect(()=>{
        document.addEventListener('keydown', someFunction); 
    }, []);

используйте хук useEffect, пустой массив в конце будет реагировать, чтобы не обновлять компонент после загрузки

Другие вопросы по тегам