关于dom事件
接触项目以来一直用的是框架,原生很多东西很基础自己却没掌握好,总结一下关于dom
事件。dom
事件指的就是dom.Event
,表示在dom 中发生的任何事件,大致可以包括:用户交互操作产生(例如鼠标或键盘事件),或者由 API 生成(例如指示动画已经完成运行的事件,视频已被暂停等等)。dom
的事件流分为三个阶段:
捕获阶段:当我们在 DOM 树的某个节点发生了一些操作(例如单击、鼠标移动上去),就会有一个事件发射过去。这个事件从 Window 发出,不断经过下级节点直到触发的目标节点。在到达目标节点之前的过程,就是捕获阶段(Capture Phase)。事件由页面元素接收,逐级向下,到具体的元素。
目标阶段:当事件不断的传递直到目标节点的时候,最终在目标节点上触发这个事件,就是目标阶段。具体的元素本身。
冒泡阶段:事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。跟捕获相反,具体元素本身,逐级向上,到页面元素(我们平时用的事件绑定就是利用的事件冒泡的原理)。
事件捕获:当使用事件捕获时,父级元素先触发,子元素后触发。
事件冒泡:当使用事件冒泡时,子元素先触发,父元素后触发
了解了事件的传递过程接下去看如何注册事件监听器,有三种注册事件监听器的方法
1.EventTraget.addEventListener
平时使用中用的教多的一种方式,包含三个参数:监听事件的类型(比如click等),具体事件(一般是一个函数),冒泡或者捕获事件(默认为false冒泡)
1 | var app = document.getElementById('app'); |
测试一下假如改变最后一个参数为true
1 | var app = document.getElementById('app'); |
看一下效果:
第三个参数 就是决定了我在冒泡的时候还是捕获的时候触发当前的事件 所以一开始默认是false 就是冒泡 当我们点击最里面事件 在最后由里向外传递的时候依次触发 然鹅当我只有把父组件的第三个参数改为true(捕获模式) 一开始点击子组件的时候才会在由外向里传递的过程中就触发了 父组件的弹窗 所以是把true放在父组件上 没毛病了😂
2.利用html属性
1 | <button onclick='alert(123456)'>我是按钮</button> |
一般不建议使用
3.dom事件属性
1 | app1.onclick = function{alert('第三种模式')} |
既然前面讲到了冒泡和捕获,在实际的项目中,因为事件捕获的存在有时候会影响我们需要的效果,举个,设计一个弹窗div
,需求是在当点击弹窗之外的遮罩层(即window部分)的时候弹窗消失,但是因为事件冒泡的原因,当点击弹窗本身也会导致弹窗消失,此时我们就需要阻止冒泡啦~
w3c阻止冒泡方法是e.stopPropagation()
,IE则是使用e.cancelBubble = true
,可以用之前的来亲测一波:
1 | var app = document.getElementById('app'); |
还有一个是事件委托,emmm…我的理解就是通过事件冒泡原理,把子元素的事件全都通过父级元素实现,比如一个ul
列表,如果要在每一个li
上绑定事件触发未免太麻烦了,于是乎我们可以把事件绑定在ul
上,事件委托还用到一个dom属性,就是event.target
,它表示触发事件的对象 (某个DOM元素) 的引用,举个:
1 | var ul2 = document.getElementById('ul2'); |
效果:
这样子我们就能捕获到每一个准确的子元素并且触发相应的事件了