请简述 DOM 事件模型或 DOM 事件机制
DOM事件流是先捕获再冒泡,事件触发则两者都可。
- DOM事件模型
-
冒泡型事件(Bubbling)先在最精确的元素上触发,然后向上传播,直到根节点。反映到DOM树上就是事件从叶子节点传播到根节点。
-
捕获型事件(Captrue)先在最顶级的元素上触发,传播到最低级的元素上。在DOM树上的表现就是由根节点传播到叶子节点。
从外向内找监听函数,叫事件捕获
从内向外找监听函数,叫事件冒泡
- 事件绑定 API:addEventListener
target.addEventListener(type, listener, useCapture);
- type 事件类型。
- listener 事件触发实际执行的匿名函数。
- userCapture 可选,类型为 Boolean,意思是是否执行事件捕获阶段。加上true则让 fn 走捕获,即当浏览器在捕获阶段发现有 fn 监听函数,就会调用 fn ,并提供事件信息。
题目
有如下的 HTML 文档结构:
<div id="parent">
<child id="child" class="child">
点我
</child>
</div>
第一次执行如下 JavaScript 代码:
document.getElementById("parent").addEventListener("click", function () {
alert(`parent 事件触发,` + this.id);
});
document.getElementById("child").addEventListener("click", function () {
alert(`child 事件触发,` + this.id);
});
第二次执行另一套 JavaScript 代码:
document.getElementById("parent").addEventListener("click", function (e) {
alert(`parent 事件触发,` + e.target.id);
});
document.getElementById("child").addEventListener("click", function (e) {
alert(`child 事件触发,` + e.target.id);
});
第三次再执行一套:
document.getElementById("parent").addEventListener("click", function (e) {
alert(`parent 事件触发,` + e.target.id);
}, true);
document.getElementById("child").addEventListener("click", function (e) {
alert(`child 事件触发,` + e.target.id);
}, true);
问题如下:
点击 id 为 child 的 div 后,这三份 JavaScript 代码的执行结果分别是什么?
答案:
- 第一次结果为:先弹出“child 事件触发,child”,再弹出“parent 事件触发,parent”。
- 第二次结果为:先弹出“child 事件触发,child”,再弹出“parent 事件触发,child”。
- 第三次结果为:先弹出“parent 事件触发,child”,再弹出“child 事件触发,child”。
关于 listener 中的 this 和 target
target 和 currentTarget( currentTarget和this很像)
- 区别
- e.target - 用户操作的元素(点击了哪个就返回哪个)
- e.currentTarget - 程序员监听的元素(哪个元素绑定了就返回哪个)
- this 是 e.currentTarget,不推荐使用它(哪个元素绑定了就返回哪个)
- 举例
- div > span{文字},用户点击文字
- e.target 就是 span
- e.currentTarget 就是 div,span没有点击事件
事件对象阻止默认行为
让链接不跳转 或者让提交按钮不提交
e.preventDefault()常用
var a = document.querySelector('a');
a.addEventListener('click', function(e) {
e.preventDefault(); // dom 标准写法
})
// 传统的注册方式
a.onclick = function(e) {
// 普通浏览器 e.preventDefault(); 方法
// e.preventDefault();
// 低版本浏览器 ie678 returnValue 属性
// e.returnValue;
// 我们可以利用return false 也能阻止默认行为 没有兼容性问题 特点: return 后面的代码不执行了, 而且只限于传统的注册方式
return false;
alert(11);
阻止冒泡
有时候不需要传播到DOM最顶层节点,则可以阻止冒泡
- 利用事件对象里面的
e.stopPropagation()方法 - IE678利用事件对象
e.cancelBubble=true
阻止事件冒泡的兼容性解决方案 (了解)
if(e && e.stopPropagation){
e.stopPropagation();
}else{
window.event.cancelBubble = true;
}
请简述事件委托
提示:「监听祖先元素」
- 原理:利用事件冒泡原理,将子元素的操作委托给父元素或是祖先元素统一管理。
- 用途:
-
当需要给后代元素执行多个重复事件时,可通过事件委托一次性管理操作来减少事件触发,节约内存。
-
动态监听元素:当需要给动态添加的元素添加事件时,必须通过事件委托来委托给父辈元素或祖先元素。