本文已参与「新人创作礼」活动,一起开启掘金创作之路
- 概念
事件:事件是用户或者浏览器自己执行的某种动作,是文档或者浏览器发生的一些交互瞬间
事件流:当一个事件被触发时,一个event对象将被创建并顺序的传递给事件监听者们。事件传递的顺序称为事件流。
事件处理程序:响应事件的函数。如click是事件名称,加上"on"开头,事件处理程序是onclick
事件在子元素和父元素之间的传播分为3个阶段:(1)捕获阶段:事件从window对象自上而下向目标节点传播的阶段;(2)目标阶段:真正的目标节点正在处理事件的阶段;(3)冒泡阶段:事件从目标节点自下而上向window对象传播的阶段。
- 事件处理程序分类 DOM0 级事件处理程序:元素节点的事件属性。在当前元素事件行为的冒泡阶段(或者目标阶段)执行的。只能绑定一个,后面的会覆盖前面的。
var btn = document.getElementById('btn');
btn.onclick = function () {
console.log('被点击了!');
}; //增加
btn.onclick = null; // 删除事件处理程序
DOM2 级事件处理程序:addEventListener()和removeEventListener()。可以同一个元素绑定多个事件。 eventType ————> 事件名称,大小写敏感 listener ————> 监听函数 useCapture ————> 可选参数,默认false,表示监听函数只在冒泡阶段被触发。
target.addEventListener(eventType, listener[, useCapture]);
DOM 3级事件:在DOM 2级事件的基础上添加了更多的事件类型。 IE9以下的IE浏览器不支持 addEventListener()和removeEventListener(),使用 attachEvent()与detachEvent() 代替,因为IE9以下是不支持事件捕获的,所以也没有第三个参数,第一个事件名称前要加on。
UI事件,当用户与页面上的元素交互时触发,如:load、scroll
焦点事件,当元素获得或失去焦点时触发,如:blur、focus
鼠标事件,当用户通过鼠标在页面执行操作时触发如:dblclick、mouseup
滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel
文本事件,当在文档中输入文本时触发,如:textInput
键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified
同时DOM3级事件也允许使用者自定义一些事件。
-
事件模型分类 W3C同时支持捕获和冒泡。事件在两个阶段都可以执行,程序员可以根据需求自行设定。 默认值为false,即在冒泡阶段执行事件函数。 捕获 捕获是从上到下,事件先从window对象,然后再到document(对象),然后是html标签(通过document.documentElement获取html标签),然后是body标签(通过document.body获取body标签),然后按照普通的html结构一层一层往下传,最后到达目标元素。 事件冒泡是IE 的事件流 冒泡 冒泡流程是捕获的逆流程。 事件捕获是Netscape浏览器开发团队提出的
-
事件委托 优点: (1)减少内存消耗,提高性能(不给每个子元素单独绑定一个事件,而只在父元素上绑定一个事件,减少了占用的内存); (2)动态绑定事件(在元素会发生变变化甚至还未创建时,可以先将事件创建好) 由于事件会在冒泡阶段向上传播到祖先节点(爸爸节点、爷爷节点),因此可以把子节点的监听函数定义在祖祖先节点上,由祖先节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)。
// 给父层元素绑定事件
document.getElementById('list').addEventListener('click', function (e) {
// 兼容性处理
var event = e || window.event;
var target = event.target || event.srcElement;
// 判断是否匹配目标元素
if (target.nodeName.toLocaleLowerCase === 'li') {
console.log('the content is: ', target.innerHTML);
}
});
// 自己封装委托函数
on('click','#div1','button',()=>{
console.log('button被点击了')
})
function on(eventType,element,selector,fn){
if(!(element instanceof Element)){
element=document.querySelector(element)
}
element.addEventlistener(eventType,(e)=>{
const t=e.target
if(t.matches(selector)){
fn(e)
}
})
}
- 事件应用 阻止默认:调用这个方法,默认事件行为将不再触发。 cancelable:true可以取消/不可取消。有些默认事件是无法取消的
event. preventDefault()
阻止a链接默认跳转的方法:
//方法一:
<a href="javascript:;">链接</a>
//方法二:
<a id="test" href="http://www.cnblogs.com">链接</a>
<script>
test.onclick = function(e){
e = e || window.event;
return false;
}
</script>
//方法三:
<a id="test" href="http://www.cnblogs.com">链接</a>
<script>
test.onclick = function(e){
e = e || window.event;
e.preventDefault();
}
</script>
阻止冒泡:event.stopPropagation() 方法阻止事件冒泡到父元素,阻止任何父事件处理程序被执行。 bubbles:true可以阻止冒泡/false不能阻止冒泡。几乎所有的事件都可以阻止冒泡 stopImmediatePropagation 既能阻止事件向父元素冒泡,也能阻止元素同事件类型的其它监听器被触发。而 stopPropagation 只能实现前者的效果。
<body>
<button id="btn">click me to stop propagation</button>
</body>
......
const btn = document.querySelector('#btn');
btn.addEventListener('click', event => {
console.log('btn click 1');
event.stopImmediatePropagation();
});
btn.addEventListener('click', event => {
console.log('btn click 2');
});
document.body.addEventListener('click', () => {
console.log('body click');
});
// btn click 1
// 使用 stopImmediatePropagation后,点击按钮时,不仅body绑定事件不会触发,与此同时按钮的另一个点击事件也不触发。
- 事件对象event.target & event.currentTarget event.target指向引起触发事件的元素,而event.currentTarget则是事件绑定的元素,只有被点击的那个目标元素的event.target才会等于event.currentTarget。也就是说,event.currentTarget始终是监听事件者,而event.target是事件的真正发出者。 如:事件监听者为div,但是点击div中的span标签时,可以冒泡触发div的事件处理程序。此时event.target是span,event.currentTarget是div。
参考: developer.mozilla.org/zh-CN/docs/… juejin.im/post/684490… juejin.im/post/684490…