我想向函数添加一个单击事件监听器,但只希望它发生一次。我怎样才能做到这一点?
如果可能的话,我也想远离 JQuery。
已编辑
由于我得到的答案并不能完全满足我的需求,我想我可以通过上下文使它更清楚一些。
我正在编写一个绘制矩形的函数,首先单击按钮来启动矩形函数。然后drawRectangle函数中有两个点击事件监听器。这些是我希望在函数中只发生一次的事件。如果用户再次单击矩形启动按钮,则允许用户创建另一个矩形。
一旦事件被触发一次,您就必须使用
removeEventListener
。然而,removeEventListener
接受一个函数作为参数,这意味着您需要声明一个命名函数,用addEventListener
添加它,然后让它删除自身。示例:
function foo() {
// do things, then
removeEventListener('click', foo);
}
addEventListener('click', foo);
function one(el, type, fn) {
function handler(event) {
el.removeEventListener(type, handler);
fn(event);
}
el.addEventListener(type, handler);
}
// use it like
one(window, 'resize', function () {
alert("This triggers just once");
});
其他答案是正确的,因为这可以通过命名函数来实现,但不需要单独声明该函数。您可以使用命名函数表达式:
element.addEventListener("click", function handler(event) {
this.removeEventListener("click", handler);
// ...
});
另一种方法(虽然不太理想)是保留一个变量来跟踪处理程序是否被执行:
var wasExecuted = false;
element.addEventListener("click", function(event) {
if (wasExecuted) {
return;
}
wasExecuted = true;
// ...
});
该变量需要在处理程序外部但在作用域内声明,以便其值在事件触发器中保持不变。
addEventListener和removeEventListener的组合:
element.addEventListener("click", clickFunction);
function clickFunction(e) {
console.log("clicked");
element.removeEventListener("click", clickFunction);
}
类似这样的事情
var el = document.getElementById('something');
el.addEventListener('click', doSomething);
function doSomething() {
el.removeEventListener('click', doSomething);
//code
}
在事件处理程序内部,您可以使用通用:
e.target.removeEventListener(e.type, arguments.callee)
function oneTimeListener(node, type, callback) {
// create event
node.addEventListener(type, function(e) {
// remove event listener
e.target.removeEventListener(e.type, arguments.callee);
// call handler with original context
// as it happens with native addEventListener
return callback.call(this, e);
});
}
oneTimeListener(document.getElementById("myElement"), "click", myHandler);
首次点击后您可以设置 cookie:
document.cookie="click=1; expires=.......";
并向侦听器添加条件 - 如果设置了 cookie,则忽略它。
我使用的另一个简单的解决方案是向我们正在监听的元素添加一个虚拟类,这样它就不会再次触发。
const myButton = document.querySelector('#my-button:not(.init)');
myButton.addEventListener('click', (e) => {
e.preventDefault();
myButton.classList.add('init');
});