如何确保事件监听器只触发一次

有时候,我们只需要监听事件一次。假设,我们有一个链接到云端的文件,但该文件没有与我们共享。在这种情况下,绑定到按钮的事件监听器应该只触发一次,以便给予我们查看文件的权限,因为一旦请求被处理,就没有必要再次处理该请求。

有两种方式可以实现:

  1. 使用once属性
  2. 在事件第一次触发后删除事件监听器

使用once属性

我们可以将一个对象作为参数传递给addEventListener方法,并指定事件仅被处理一次。这可以通过将属性once传递给对象来实现。如果我们将once设置为true,则事件只会被触发一次。

let btn = document.getElementById('btn');
btn.addEventListener("click", function() {
    // onClick code
}, {once : true});

在事件第一次触发后删除事件监听器

我们将为具有处理函数的元素绑定一个事件监听器,并在处理函数内部删除为该元素添加的事件。

let btn = document.getElementById('btn');
function onClick(event){
   btn.removeEventListener('click', onClick);
   console.log("Event fired once, no more click will be handled");
}

btn.addEventListener('click', onClick);

以下代码展示如何创建一个通用函数来处理所有事件和元素。

function oneTimeListener(node, type, callback) {
    // create event
    node.addEventListener(type, function listener(e) {
        // remove event listener
        e.target.removeEventListener(e.type, listener);
        // call handler with original context 
        return callback.call(this, e); 
    });
}

let btn = document.getElementById('btn');
function onClick(event){
   console.log(event, this);
}
oneTimeListener(btn, 'click', onClick);

在上述代码中,我们向DOM元素添加了事件监听器。一旦事件第一次触发,我们就会删除绑定到它的事件监听器。这样,就像事件只被处理了一次一样。

扩展

Vue

Vue为v-on提供了事件修饰符once来指定事件最多触发一次

<button v-on:click.once="doThis"></button>

React

React中可以用ref来实现,其实还是用的addEventListener

import React, { useEffect, useRef } from 'react'

const App = () => {
  const ref = useRef()
  // 等待DOM加载
  useEffect(() => ref.addEventListener('click', () => alert('Hi'), { once: true })
  return <button ref={ref}>Click on me (once)</button>
}

来源How to ensure an event listener is only fired once in JavaScript

posted @ 2018-05-15 18:09  伊卡洛斯之翼Chris  阅读(5571)  评论(0)    收藏  举报