事件流
定义: 每个事件发生时,都有一个触发并执行的过程,也就是事件的传播过程,我们称之为事件流,简单地说事件流就是事件从触发到执行结束的流程
事件流的三个阶段
-
捕获阶段
事件从顶级元素触发,然后逐渐向下传播,直到目标元素,依次执行其身上绑定的事件
-
目标阶段
触发当前自身的事件
-
冒泡阶段
事件由目标元素接收,然后逐渐向上传播,达到最顶层元素,依次执行其身上绑定的事件
事件流模型
事件执行的流程是
- 捕获阶段 ---> 目标阶段 ---> 冒泡阶段
- 目标元素的事件是在目标阶段执行,其它事件会在冒泡阶段执行。每个事件只会执行一次,也就是说如果在冒泡阶段执行了事件,就不会在捕获阶段执行
事件级别
DOM标准:
类似于 ES6 和 ES5 版本变更
-
DOM0
事件处理函数绑定
<body> <button id="box">box</button> <script> box.onclick = function(){ console.log("我是box"); } </script> </body> -
DOM1
没有定义相关事件的写法
-
DOM2
新增
addEventListene(type,callback,useCapture)small.addEventListener('click',function(){ console.log(this); })注意:useCapture
-
DOM3 DOM4
事件委托
事件对象
-
兼容性处理
small.addEventListener('click',function(ev){ var e = ev || window.event },true) -
事件对象常用属性
-
-
e.type
-
e.target
选中的元素(点击就是点击元素,划入就是划入元素)
存在兼容性问题
var target = e.target || e.srcElement-
e.cueerntTarget
绑定事件处理函数对应的的DOM元素
small.addEventListener('click',function(ev){ var e = ev || window.event console.log(e.type); // 事件类型 },true)target和currentTarget的区别是:
- target:触发事件的元素currentTarget:事件绑定的元素
- 两者在没有冒泡的情况下,是一样的值,但在用了事件委托的情况下,就不一样了
-
案列
一个ul里面包括几百个li,如果给每个li都绑定事件,十分耗费性能,通过事件委托,给父级元素绑定一个事件,通过冒泡机制和e.target判断是那个li被触发了
<body>
<ul id='box'>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
box.onclick = function(e){
var target = e.target || e.srcElement
console.dir(target.innerHTML);
}
</script>
</body>
取消事件冒泡 和 捕获
w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true
e. bubbles属性值
e.bubbules //true代表可以冒泡 false达标不可以冒泡
js中基本所有事件都可以冒泡,除了
1. focus
2. onblur
3. onSroll
-
stopPropagation
- stopPropagation:阻止冒泡和捕获
big.addEventListener('click',function(ev){ var e = ev || window.event console.log('outer'); }) small.addEventListener('click',function(ev){ var e = ev || window.event e.stopPropagation() # 阻止冒泡,不能阻止多个事件,如果small绑定了多个函数 console.log('inner1'); }) small.addEventListener('click',function(ev){ var e = ev || window.event e.stopPropagation() # 阻止冒泡,不能阻止多个事件,如果small绑定了多个函数 console.log('inner2'); }) -
stopImmediatePropagation
-
不仅可以取消冒泡和捕获,还可以取消同一个事件的其它监听函数被调用
big.addEventListener('click',function(ev){ var e = ev || window.event console.log('outer'); }) small.addEventListener('click',function(ev){ var e = ev || window.event e.stopImmediatePropagation() console.log('inner1'); }) small.addEventListener('click',function(ev){ var e = ev || window.event console.log('inner2'); })
-
-
cancleBubble
big.addEventListener('click',function(ev){ var e = ev || window.event console.log('outer'); }) small.addEventListener('click',function(ev){ var e = ev || window.event e.cancelBubble = true console.log('inner1'); })
兼容性处理方案
function cancelBubble(e){
var e = e || window.event
if(e.stopPropagation){
e.stopPropagation()
}else{
e.cancelBubble = true
}
}
注意事项
-
所有事件都会冒泡到window上吗?
现代浏览器 IE9+