jQuery one() 的 JS 等效方法是什么?

17

有人能为我提供下面问题的解决方案吗?我正在尝试找到一个JS等效的jQuery代码:

var formSelector = 'my selector here';
var attribute = 'name';
var formHistory = [];

$(formSelector).one('focusout', function(e) {
    formHistory.push(e['target'].getAttribute(attribute));
});

3
你可以使用addEventListener()来附加事件,然后在其中使用removeEventListener()来移除它。注意我没有测试过。 - DontVoteMeDown
5个回答

28

更新

在大多数浏览器中,您现在可以在选项对象中传递once:true

document.getElementById('btn').addEventListener('click', () => {
  console.log('Hello and goodbye');
}, {
  once: true,
});
<button id="btn">Click me</button>


旧的方法

在事件监听器回调函数中,只需销毁事件监听器即可 :) 下面是一个帮助函数:

function oneTimeEvent(element, eventType, callback) {
  element.addEventListener(eventType, function(e) {
    e.target.removeEventListener(e.type, arguments.callee);
    return callback(e);
  });
}

var btn = document.querySelector('button');
oneTimeEvent(btn, 'click', function () {
  alert('♫ You clicked me once, but I won\'t let you click me twice, yeah!');
});
<button>Click me!</button>


5
在将函数绑定到事件之前先声明函数可能是个好主意,这样当解除绑定时可以引用该函数(而不是arguments.callee)。使用callee是极其不推荐的。 - ssube
有没有一种方法可以删除 arguments.callee,但保留使用匿名函数名称/多个不同函数的能力? - Lovethenakedgun
1
这个答案是几年前给出的。现在你实际上可以将 addEventListener 传递一个选项对象,其中包含属性 once: true - Phillip

10

这里有一个使用数据属性的非常简单的解决方案。

document.querySelector('#click').addEventListener('click', function(e){
    if(e.currentTarget.dataset.triggered) return;
    e.currentTarget.dataset.triggered = true;
    alert('clicked');
})
<button id="click">Click me</button>


谢谢,乔纳森!这正是我正在寻找的。 - quarrazzella
2
这个答案并没有移除事件,因此其他能够移除事件的解决方案更好。只需要添加 e.removeEventListener 即可。 - bArmageddon

8

2

使用ES6和一些闭包,这是一个不错的方法。

const button = document.querySelector('button');

function composeHandler(element, event, handler, ...captureArgs) {
  return function handlerFunc (...args) {
   handler(...args);
    element.removeEventListener(event, handlerFunc, ...captureArgs);
  }
}

function addEventListenerOnce(element, event, handler, ...captureArgs) {
 element.addEventListener(event, composeHandler(element, event, handler, ...captureArgs), ...captureArgs);
}

addEventListenerOnce(button, 'click', (e) => alert('clicked on button ' + e.target.innerText), true)
<button>
  Click me once!
</button>


0

尝试编写您的one实现。就像这样:

function one(element,eventType,callback,self) {
    var one=function(event) {
        try{
            callback.call(self,event);
        } finally {
            element.removeEventListener(eventType,one);
        }
    }
    element.addEventListener(eventType,one);    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接