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, пустой массив в конце будет реагировать, чтобы не обновлять компонент после загрузки