DOM事件流
一、定义
DOM事件流指的是从页面接收事件的顺序。这个路径包括了事件的捕获阶段、目标阶段和冒泡阶段。
图片来源黑马pink老师PPT
二、事件流阶段
DOM事件流涉及三个主要阶段:
捕获阶段(Capturing Phase):
- 事件从文档的根节点(如document对象)开始,沿着DOM树向下传播,直到到达事件的目标节点(即触发事件的元素)。
- 在这个阶段,事件会经过目标节点的所有祖先节点,并触发这些节点上设置的捕获阶段事件监听器(如果有的话)。
- 默认情况下,大多数浏览器不支持或不在此阶段触发事件监听器,除非在addEventListener方法中明确指定。
目标阶段(Target Phase):
- 当事件到达目标节点时,事件在该节点上被触发,并执行该节点上绑定的事件处理函数。
- 这个阶段没有冒泡或捕获的概念,只是简单地处理目标节点上的事件。
冒泡阶段(Bubbling Phase):
- 事件从目标节点开始,沿着DOM树向上传播,经过所有祖先节点,直到到达文档的根节点。
- 在这个过程中,事件会触发每个经过的节点上设置的事件监听器(默认是冒泡阶段)。
- 如果没有在捕获阶段或目标阶段被阻止,事件将继续冒泡。
图片来源黑马pink老师
三、事件处理
在DOM事件流中,每个元素都可以有自己的事件处理程序,这些处理程序被称为事件监听器或事件处理函数。可以通过以下方式向元素添加事件监听器:
- 对象属性绑定:如element.onclick = function() {...}。这种方式只能绑定一个事件处理函数,重复绑定会覆盖之前的函数。
- addEventListener()方法:如element.addEventListener('click', function() {...}, [useCapture])。这种方式可以绑定多个事件处理函数,且可以指定事件是在捕获阶段还是冒泡阶段触发(通过useCapture参数,true为捕获阶段,false为冒泡阶段,默认为false)。
捕获阶段:第三个参数是true
javascript"> //DOM事件流的验证://捕获顺序:window -> document -> body -> div.father -> div.son//冒泡顺序:div.son -> div.father -> body -> document -> window//先执行father的click事件,然后执行son的click事件,最后执行window的click事件。
var son=document.querySelector('.son');
son.addEventListener('click',function(e){alert('捕获阶段2');
},true);var father=document.querySelector('.father');father.addEventListener('click',function(e){alert('捕获阶段1');},true);
冒泡阶段:第三个参数是false或者省略
javascript"> //冒泡阶段var son=document.querySelector('.son');
son.addEventListener('click',function(e){alert('son');
},false);var father=document.querySelector('.father');father.addEventListener('click',function(e){alert('father');},false);document.addEventListener('click',function(){alert('document');});
四、阻止事件冒泡
在事件冒泡的过程中,可以通过调用事件对象上的stopPropagation()方法来阻止事件继续向上冒泡。此外,在Internet Explorer中,还可以通过设置事件对象的cancelBubble属性为true来达到同样的效果。
五、应用与注意事项
1. JS代码中只能执行捕获或者冒泡其中的一个阶段。
2. onclick 和attachEvent 只能得到冒泡阶段。
3. addEventListener (type, listener [, useCapture] )第三个参数如果是true ,表示在事件捕 获阶段调用事件处理程序;如果是false (不写默认就是false ) , 表示在事件冒泡阶段调用事件处理程序。
4.实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
5.有些事件是没有冒泡的,比如onblur、onfocus、 onmouseenter、 onmouseleave
事件对象
一、定义
- et就是一个对象,包含了事件的所有信息,包括事件类型、事件源、事件目标等。当形参来看
- 事件对象有了事件才会存在,否则不存在
- 事件对象可以自己命名event \e\eve
- IE678通过window.event获取事件对象
- 兼容性写法:e=e||window.e;
javascript"> <div>111</div><script>var div=document.querySelector("div");div.addEventListener("click", function(e){div.style.backgroundColor="blue";console.log(e);});</script>
输出:
二、事件对象常见的方法和属性
常见属性
常见属性 | 说明 |
type | 返回事件的类型,如click、keydown、mouseover等 |
target | 返回触发事件的元素 |
currentTarget | 返回其事件监听器触发该事件的元素 |
eventPhase | 返回事件传播的当前阶段,返回的值含义(0,表示事件不在传播过程中)、(1,表示事件正在捕获阶段传播)、(2,表示事件到达目标元素)、(3,表示事件正在冒泡阶段传播) |
bubbles | 返回一个布尔值,指示事件是否冒泡 |
cancelable | 返回一个布尔值,表示事件是否可以取消只有可以取消的事件(如submit事件)的preventDefault()方法才会起作用 |
timeStamp | 返回事件发生的时间戳(自1970年1月1日00:00:00 UTC起计算的毫秒数) |
clientX/clientY | 返回鼠标事件发生时,鼠标指针相对于浏览器窗口可视区的水平/垂直坐标 |
pageX/pageY | 返回鼠标事件发生时,鼠标指针相对于整个文档的水平/垂直坐标(包括滚动的偏移量) |
代码示例
javascript"> div.addEventListener("click", function(e){div.style.backgroundColor="blue";console.log(e);console.log(e.target);console.log(this);console.log(e.type);console.log(e.eventPhase);});
常见方法
方法 | 说明 |
preventDefault() | 阻止事件的默认行为,例如,阻止链接的默认跳转行为或表单的默认提交行为 |
stopPropagation() | 阻止事件进一步传播(冒泡或捕获) |
stopImmediatePropagation() | :除了调用stopPropagation()的方法外,stopImmediatePropagation还会阻止相同事件的其他监听器被调用(如果它们绑定在当前元素上) |
composedPath() | 返回一个数组,包含事件传播路径上的所有DOM节点 |
1.preventDefault() 方法示例
javascript"><form id="myForm" action="/submit-form"> <input type="submit" value="提交">
</form> <script> document.getElementById('myForm').addEventListener('submit', function(event) { event.preventDefault(); // 阻止表单的默认提交行为 console.log('表单提交被阻止'); });
</script>
2. stopPropagation()
方法示例
javascript"><div id="parent" style="padding: 20px; border: 1px solid #000;"> <button id="child">点击我</button>
</div> <script> document.getElementById('parent').addEventListener('click', function(event) { console.log('Parent clicked'); }); document.getElementById('child').addEventListener('click', function(event) { event.stopPropagation(); // 阻止事件冒泡 console.log('Child clicked'); });
</script>
拓展this和target的区别
1.this返回的是绑定是按的对象(元素) /// e.target返回的是触发事件的对象(元素)
2.代码示例
javascript"> var ul=document.querySelector('ul');ul.addEventListener('click', function(e){//this指向ulconsole.log(this);//e.target指向li触发事件的对象console.log(e.target);console.log(e.target.tagName);console.log(e.target.parentNode);console.log(e.target.nextSibling);})
结果:
事件委托
事件委托的步骤
- 确定事件绑定在哪个父元素上:这个父元素需要包含所有目标子元素,且最好在DOM结构中位于一个较低层次
- 编写事件处理函数:在这个函数中,通过event.target属性来获取实际触发事件的元素(即事件的目标元素)。event.target始终指向触发事件的元素,即使在事件冒泡过程中。
- 检查event.target是否符合预期:在事件处理函数中,可以通过比较event.target的某些属性(如id、class、tagName等)来确定是否需要对该事件进行响应。
- 执行相应的操作:如果event.target符合条件,则执行相应的操作。
代码
javascript"> <ul><li>希望在于自己</li><li>希望在于自己</li><li>希望在于自己</li><li>希望在于自己</li></ul><script>var ul=document.querySelector("ul");ul.addEventListener("click",function(e){//判断是否为li标签//toLowerCase() 用于将字符串中的所有大写字母转换为小写字母if(e.target.tagName.toLowerCase() === "li"){e.target.style.backgroundColor = "pink";alert("点击了"+e.target.innerHTML);}});</script>