浏览器系列 -- 原生实现添加事件和移除事件

1,535 阅读2分钟

本文转载自 blog.csdn.net/qq_29606781…

一、addEventListener() 和 removeEventListener() 讲解

  • 添加事件:dom.addEventListener("事件名" , "事件处理函数" , "布尔值");
  • 移除事件:dom.removeEventListener("事件名" , "事件处理函数" , "布尔值");

参数详解

  • 第一个参数

事件名的选值见 HTML DOM 事件列表 【记得去掉 on 才是事件名】

  • 第二个参数

    • 命名函数,则 removeEventListener 可以指定同一个事件处理函数移除 addEventListener 添加的事件
    • 无名函数,则 removeEventListener 移除不了了
// 错误写法
document.body.addEventListener('touchmove', function (event) {
    event.preventDefault();
},false);
document.body.removeEventListener('touchmove', function (event) {
    event.preventDefault();
},false);
// 错误原因:addEventListener() 和 removeEventListener() 传入的函数不是同一个(内存地址不同)

// 正确写法
function bodyFunction(event){
    event.preventDefault();
}
document.body.addEventListener('touchmove',bodyFunction,false); // 注意调用时不能传入参数,也不要加()
document.body.removeEventListener('touchmove',bodyFunction,false);

注意:通过 addEventListener() 添加的事件处理程序只能使用 removeEventListener() 来移除

event 对象的属性和方法:

image.png

  • 第三个参数

现在的版本可以省略第三个参数,默认值为 false。true 和 false 的区别见下方

二、addEventListener()与removeEventListener()的第三个参数详解

布尔值参数是 true,表示在捕获阶段调用事件处理程序;

如果是 false,在冒泡阶段调用事件处理程序;

image.png

由图可知捕获过程要先于冒泡过程,即 true 的触发顺序在 false 前面

HTML内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加事件&&解绑事件</title>
</head>
<body>
    <div id="out">
        <p>最外面</p>
        <div id="middle">
            <div id="inner">最里面</div>
        </div>
    </div>
</body>
</html>

js内容:(第1种情况)

<script>
  var out = document.getElementById('out'); 
  var middle = document.getElementById('middle'); 
  var inner = document.getElementById('inner'); 
  //点击inner时,触发顺序为:inner-------middle------out
  out.addEventListener('click',function(){alert("我是最外面的");},false);   
  middle.addEventListener('click',function(){alert("我是中间的");},false);    
  inner.addEventListener('click',function(){alert("我是最里面的");},false); 
</script>

js内容:(第2种情况)

<script>
  //点击inner时,触发顺序为:out------middle-------inner
  out.addEventListener('click',function(){alert("我是最外面的");},true);   
  middle.addEventListener('click',function(){alert("我是中间的");},true);  
  inner.addEventListener('click',function(){alert("我是最里面的");},true); 
</script>

js内容:(第3种情况)

<script>
  //点击inner时,触发顺序为:out------inner-------middle
  out.addEventListener('click',function(){alert("我是最外面的");},true);   
  middle.addEventListener('click',function(){alert("我是中间的");},false);    
  inner.addEventListener('click',function(){alert("我是最里面的");},false);
</script>

js内容:(第4种情况)

<script>
  //点击inner时,触发顺序为:out-------middle------inner
  out.addEventListener('click',function(){alert("我是最外面的");},true);   
  middle.addEventListener('click',function(){alert("我是中间的");},true);  
  inner.addEventListener('click',function(){alert("我是最里面的");},false);
</script>

...(其余情况就不列举了)

规律

  1. true 的优先于 false 的;
  2. 如果存在多个 true 的,则外层触发先于内层
  3. 如果存在多个 false 的,则内层触发先于外层

附加内容

参考 onclick=function 与 addEventListener('click',function) 区别 文章得到二者区别:

  1. addEventListener 给一个事件注册多个 listener;而 onclick 只能给事件注册一个 listener,如果有多个 listener 就只算最后一个
<div id = "aaa" />
<div id = "bbb" />
<script>
  var aaa = getElementById("aaa");
  aaa.onclick = function(){ console.log('aaa1') };
  aaa.onclick = function(){ console.log('aaa2') };
  // 点击 aaa 只打印出 'aaa2'
  var bbb = getElementById("bbb");
  bbb.addEventListener("click",function(){ console.log("bbb1") },false);
  bbb.addEventListener("click",function(){ console.log("bbb2") },false);
  // 点击 bbb 会依次打印出 bbb1、bbb2
</script>
  1. addEventListener 可以控制 listener 的触发阶段,(捕获/冒泡)。控制的原理就是通过第三个参数去控制的。对于多个相同的事件处理器,不会重复触发,不需要手动使用 removeEventListener 清除