事件事件流
事件是与浏览器交互的瞬间,如点击按钮,填写表格等,它是js与html之间交互的桥梁。
事件流有两种:
- 事件冒泡:是一种从下网上的传播方式。事件最开始由具体的元素,然后逐渐向上传播到最不具体的那个节点,也就是DOM种最高层的父节点。
- 事件捕获:与事件冒泡相反。事件最开始由不太具体的节点最早接受事件,而最具体的节点最后接受事件。
事件模型
JavaScript中的事件模型主要分为3种:原市事件模型、DOM2事件模型、IE事件模型
-
DOM0级模型
这是一种被所有浏览器都支持的事件模型,有两种方式实现:
(1) 在html代码种直接指定属性值:<button onclick= "handleCilck()" /> (2) 在js代码中:document.getElementById('demo').onclick = function(){} 优点: - 兼容所有浏览器 缺点: - 相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的。 - 无法通过实现事件的捕获、委托等机制。
-
DOM2事件模型
此模型事W3C指定的标准模型,兼容除了IE6-8之外所有浏览器。
W3C制定的事件模型种,一次事件的发生包含三个过程:(1) 事件捕获阶段:事件从document一直向下传播到目标元素,依次检查经过的节点是否并定了事件监听函数,如果有则执行。 (2) 事件目标阶段:事件到达目标元素,触发目标元素的监听函数。 (3) 事件冒泡阶段:事件从目标元素冒泡到document,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。
事件绑定监听函数:
addEventListener(eventType, handler, useCapture)
事件移除监听函数:
removeEventListener(eventType, handler, useCapture)
参数说明:
- eventType指定事件类型(不要加on) - handler是事件处理函数 - useCapture是一个boolean,设置false为冒泡,true为捕获
例子:
var btn = document.getElementById('btn'); btn.addEventListener('click', function(){ console.log('123'); }, false);
我们可以通过实际操作来看一下 捕获 和 冒泡 的顺序:
首先设置内中外三层盒子<div class="border"> <div class="box"> <div class="content"></div> </div> </div>
再给每一层都加上冒泡和捕获var oBorder = document.getElementsByClassName('border')[0]; var oBox = document.getElementsByClassName('box')[0]; var oContent = document.getElementsByClassName('content')[0]; oBorder.addEventListener('click', function(){ console.log('冒泡--我是外层') }, false) oContent.addEventListener('click', (e) => { console.log('冒泡--我是内层') }, false) oBox.addEventListener('click', (e) => { console.log('冒泡--我是中间'); }, false) oContent.addEventListener('click', function(){ console.log('捕获--我是内层') }, true) oBox.addEventListener('click', function(){ console.log('捕获--我是中层') }, true) oBorder.addEventListener('click', function(e){ console.log('捕获--我是外层'); }, true)
当我们点击黄色区域时,我们来看一下打印结果:
通过结果我们可以得知:外层元素先触发捕获,后触发冒泡。内层元素先触发冒泡,再触发捕获。而事件触发顺序和事件绑定先后顺序没有关系。 -
IE事件模型
IE事件模型共有两个过程:
- 事件处理阶段。事件达到目标元素,触发目标元素的监听函数。 - 事件冒泡阶段。事件从目标元素冒泡到document,依次检查经过的节点是否绑定了事件监听函数,如果有则执行。
IE事件绑定监听函数的方式如下:
aattachEvent(eventType, handler)
IE事件移除监听函数的方式如下:
detachEvent(eventType, handler)
参数说明:
参数和addEventListener中的前两个参数一样,只是少了最后一个参数。
事件对象
当一个事件被触发时,会创建一个事件对象(Event Object),这个对象里面包含了与该事件相关的属性或者方法。该对象会作为第一个参数传递给监听函数。
- DOM事件模型种的事件对象常用属性:
- stopPropageation() 阻止事件冒泡
- target 获取事件目标
- preventDefault()阻止事件默认行为
- IE事件模型种的事件对象常用属性
- cancelBubble 阻止事件冒泡
- srcElement 获取事件目标
- returnValue 阻止事件默认行为
事件代理
事件在冒泡过程种会上传到父节点,因此可以把子节点的监听函数定义在父节点上,由富姐点的监听函数统一处理多个子元素的事件,这种方式称为事件代理。
我们有一个 ul 里面由 7 个 li:
<ul id="border">
<li>我是第一个li</li>
<li>我是第二个li</li>
<li>我是第三个li</li>
<li>我是第四个li</li>
<li>我是第五个li</li>
<li>我是第六个li</li>
<li>我是第七个li</li>
</ul>
我们现在想实现点击 li 弹出每个 li 的内容(我们可以在父节点上一次性的为所有子节点注册监听函数)
var oUl = document.getElementById('border');
oUl.addEventListener('click', function(e){
console.log(e.target.innerText);
}, false)
点击每个li,正确打印出结果: