addEventListener与removeEventListener实际应用

简单使用

addEventListener添加监听事件函数,有三个参数

  • 第一个参数:监听动作(必须)
  • 第二个参数:触发函数(必须)
  • 第三个参数:一个bool类型。当为false时为冒泡获取(由里向外),true为capture方式(由外向里)。(可选)

关于第三个参数为事件冒泡方式,不在本文说明范围之内!

removeEventListener移除解绑监听事件函数,有两个参数。

  • 第一个参数:监听动作(必须)
  • 第二个参数:绑定动作指定的函数体(必须)

实例1,直接在参数内传入一个匿名函数体:

element.addEventListener('click', function () {
  alert('Hello word!');
});

这种方式最简便,但不能解绑监听动作,如以下代码是无效的:

// 这种解绑方式是无效的
element.removeEventListener('click', function () {
  alert('Hello word!');
});

实例2,传入函数变量

var handle = function () {
  alert('Hello word!');
};

element.addEventListener('click', handle);

如果要解绑监听事件很容易,如下:

element.removeEventListener('click', handle);

复杂应用

然而实际业务需要还是复杂的很多,仍然需要我们精心设计。

var main = function () {
 
  // 获取节点
  var button = document.querySelectorAll('button');

  // 获取一个随机数
  var rand = Math.random();

  // 单击处理函数
  var clickHandle = function () {
    console.log(rand);
  };

  // 添加单击事件
  button[0].addEventListener('click', clickHandle);
};  
 
window.onload = main;

以上代码是一个很普通的业务,处理函数体内能访问到rand变量是因为处理函数clickHandle是在main函数里声明的。假如处理函数来自别处,如:

// 单击处理函数
var clickHandle = function () {
  // rand访问不到
  console.log(rand);
};
 
var main = function () {
 
  // 获取节点
  var button = document.querySelectorAll('button');

  // 获取一个随机数
  var rand = Math.random();

  // 添加单击事件
  button[0].addEventListener('click', clickHandle);
 
};

这样rand就访问不到了,所以对于addEventListener里的函数体如何传参数呢?我们可以这样做:

// 单击处理函数
var clickHandle = function (rand) {
  return function(){
    console.log(rand);
  };
};
 
var main = function(){
 
  // 获取节点
  var button = document.querySelectorAll('button');

  // 获取一个随机数
  var rand = Math.random();

  // 添加单击事件 把rand传入
  button[0].addEventListener('click', clickHandle(rand));
 
};  
 
window.onload = main;

clickHandle先接收参数,然后再return一个匿名函数,这样就解决了addEventListener函数体传参的问题,然而上面的方案并不是很完美,因为不能解绑

// 虽然传入的参数相同,返回的函数也一样,但这样是无效的操作
button[0].removeEventListener('click', clickHandle(rand));

因为JavaScript不能像Python能打出ID值,但我觉得removeEventListener解绑时,会根据传入函数变量的内存指向地址去搜寻addEventListener时传入函数的内存地址是否匹配,如果匹配就可以执行解绑操作。比如下面这个DEMO就很好的说明了这个问题:

index.html

<button>alert</button>

app.js

var main = function(){
 
  // 获取节点
  var button = document.querySelectorAll('button');

  var handle1 = function () {
    console.log('handle1');
  };

  var handle2 = function () {
    console.log('handle2');
  };

  button[0].addEventListener('click', handle1);
  button[0].addEventListener('click', handle2);
 
};

给button添加了两个click事件,分别对应不同的handle,单击button后,会分别打出出handle1与handle2。此时,我们可以通过以下代码解绑其中一个监听事件,但不会影响其它事件的监听

// 移除handle1的监听
button[0].removeEventListener('click', handle1);

因此回来看刚才的例子,完美解决方案的应该是这样:

// 单击处理函数
var clickHandle = function (rand) {
  return function(){
    console.log(rand);
  };
};
 
var main = function(){
 
  // 获取节点
  var button = document.querySelectorAll('button');

  // 获取一个随机数
  var rand = Math.random();

  // 获得匿名函数
  var handle = clickHandle(rand);

  // 添加单击事件 把rand传入
  button[0].addEventListener('click', handle);

  // 移除绑定事件
  button[0].removeEventListener('click', handle);
};
 
window.onload = main;

没有一个API能查出一个节点被添加了哪些事件,这是一个问题,只能通过代码设计解决!

分享

TITLE: addEventListener与removeEventListener实际应用

LINK: https://www.qttc.net/382-addeventlistener-removeeventlistener.html

NOTE: 原创内容,转载请注明出自琼台博客