DOM 事件模型和事件委托

先了解下点击事件
//.爷爷>.爸爸>.儿子, 给3个div分别添加事件监听fnYe/fnBa/fnEr
<div class="爷爷">
    <div class="爸爸">
        <div class="儿子">文字</div>
    </div>
</div>
/*
其中文字(示例代码中)就是事件监听和事件冒泡的目标.因此DOM事件模型分为3个阶段:
(1)捕获阶段:事件从window对象自上而下向目标节点传播的阶段(示例代码中简化为: 爷爷->爸爸->儿子);
(2)目标阶段:真正的目标节点正在处理事件的阶段;(示例代码中: 文字)
(3)冒泡阶段:事件从目标节点自下而上向window对象传播的阶段(示例代码中简化为: 儿子->爸爸->爷爷)。
*/

提问1: 点击了谁?
点击文字, 算不算点击儿子
点击文字, 算不算点击爸爸
点击文字, 算不算点击爷爷
答: 都算

提问2: 调用顺序? 点击文字最先调用fnYe/fnBa/fnEr中的哪一个函数?
答: 都行.
IE5调用顺序为fnEr->fnBa->fnYe
网景调用顺序为fnYe->fnBa->fnEr

因此W3C在2002年发布了标准
文件名为DOM Level 2 Events Specification
规定浏览器同时支持两种调用顺序
首先按爷爷->爸爸->儿子顺序看有没有函数监听
然后按儿子->爸爸->爷爷顺序看有没有函数监听
有监听函数就调用,并提供事件信息,没有就跳过

结论

因此, 用专业术语来说这2种顺序分别就是DOM事件模型的事件捕获和事件冒泡.一个事件发生后,会在子元素和父元素之间传播(propagation)

  1. 事件捕获:从外到内找监听函数
  2. 事件冒泡:从内到外找监听函数
图例显示

在这里插入图片描述

事件绑定
  • IE5*: xxx.attachEvent(‘onclick’,fn);//事件冒泡
  • 网景: xxx.addEventListener(‘click’,fn);//事件捕获
  • W3C: xxx.addEventListener(‘click’,fn,bool);//如果bool不传或者为falsy,则fn使用事件冒泡,反之则fn使用事件捕获
  • 图例
    在这里插入图片描述
DOM事件级别

DOM级别一共可以分为四个级别:DOM0级、DOM1级、DOM2级和DOM3级。而DOM事件分为3个级别:DOM 0级事件处理,DOM 2级事件处理和DOM 3级事件处理。由于DOM 1级中没有事件的相关内容,所以没有DOM 1级事件。

  1. DOM 0级事件
    el.οnclick=function(){}
var btn = document.getElementById('btn');
 btn.onclick = function(){
     alert(this.innerHTML);
 }

当希望为同一个元素/标签绑定多个同类型事件的时候(如给上面的这个btn元素绑定3个点击事件),是不被允许的。DOM0事件绑定,给元素的事件行为绑定方法,这些方法都是在当前元素事件行为的冒泡阶段(或者目标阶段)执行的。

  1. DOM 2级事件
    el.addEventListener(event-name, callback, useCapture)
    event-name: 事件名称,可以是标准的DOM事件
    callback: 回调函数,当事件触发时,函数会被注入一个参数为当前的事件对象 event
    useCapture: 默认是false,代表事件句柄在冒泡阶段执行
var btn = document.getElementById('btn');
btn.addEventListener("click", test, false);
function test(e){
	e = e || window.event;
    alert((e.target || e.srcElement).innerHTML);
    btn.removeEventListener("click", test)
}
//IE9-:attachEvent()与detachEvent()。
//IE9+/chrom/FF:addEventListener()和removeEventListener()

IE9以下的IE浏览器不支持 addEventListener()和removeEventListener(),使用 attachEvent()与detachEvent() 代替,因为IE9以下是不支持事件捕获的,所以也没有第三个参数,第一个事件名称前要加on。

  1. DOM 3级事件
    在DOM 2级事件的基础上添加了更多的事件类型。

UI事件,当用户与页面上的元素交互时触发,如:load、scroll
焦点事件,当元素获得或失去焦点时触发,如:blur、focus
鼠标事件,当用户通过鼠标在页面执行操作时触发如:dblclick、mouseup
滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel
文本事件,当在文档中输入文本时触发,如:textInput
键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified
同时DOM3级事件也允许使用者自定义一些事件。

事件委托

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件

原理
  1. 事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢
  2. 就是事件从最深的节点开始,然后逐步向上传播事件
场景一:你要给10个按钮添加点击事件,咋办?

答:监听它们的祖先,等冒泡的时候判断 target 是不是这10个里面的一个
代码如下:

<body>
   <div id="div1">  
       <button>click 1</button>  
       <button>click 2</button>  
       <button>click 3</button>  
       <button>click 4</button>  
       <button>click 5</button>  
       <button>click 6</button>  
       <button>click 7</button>  
       <button>click 8</button>  
       <button>click 9</button>  
       <button>click 10</button>  
     </div>  
</body>
div1.addEventListener ('click',(e) => {
    const t = e.target;
    if(t.tagName.toLowerCase() === "button"){   
        console.log("我被点击啦");
        console.log("button 被点击了" + t.textContent);
    }
});
场景二:你要监听目前不存在的元素的点击事件,咋办?

答:监听祖先,等点击的时候看看是不是我想监听的元素即可

setTimeout (() => {
    const btn = document.createElement('button');
    btn.textContent = 'click 1';
    div1.appendChild(btn);
},1000);
div1.addEventListener('click',(e)=>{
    const t = e.target;
    if(t.tagName.toLowerCase() === 'button'){
        console.log('button click');
    }
});
优点
  1. 省监听数(内存)
  2. 可以监听动态元素
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaobangsky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值