前言
本篇章主要讲述DOM事件流相关内容,事件流与js事件机制是两回事,前者指的是浏览器对于用户操作的反应流程,后者是函数在js环境下的执行顺序。
面试回答
1.事件流:事件流就是浏览器对于用户操作的反应流程,它主要由三个阶段组成,捕获阶段、目标阶段、冒泡阶段,冒泡阶段会依次从目标元素,逐级向上传播触发,绑定的同名事件。大部分的事件都会按照这三个阶段去执行,但有些事件会跳过冒泡阶段,比如聚焦、失焦事件。
知识点
事件流分为三个阶段:捕获阶段、目标阶段、冒泡阶段。捕获阶段是由顶层元素触发,然后逐级向下传播,直到目标元素。目标阶段是触发当前自身的事件。冒泡阶段是由目标元素逐级向上传播,依次执行元素绑定的同名事件。
1.DOM事件流
javascript和HTML之间的交互是通过事件实现的,而事件就是用户或浏览器自身执行的某种动作,比如点击、加载,鼠标移入移出等等。上述描述的事件流即为DOM事件流,大部分的事件都会依照事件流的方式去执行,但有些事件会跳过冒泡阶段,例如聚焦focus事件、失焦blur事件。
常见的事件如下,
UI事件:load、unload、error、select、resize、scroll
焦点事件:blur、focusout 、focus、focusin
鼠标事件:click、mousedown、mouseup、mouseenter、mouserleave、mousemove、mouseout、mouseover
滚轮事件:mousewheel
键盘事件:keydown、keypress、Keyup 用户释放键盘上的建时触发
HTML5事件:contextmenu、beforeunload、DOMContentLoad、readystatechange、pageshow、pagehide、hashchange
常见的事件对象如下,
event:在触发 DOM 上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息。所有的浏览器都支持 event 对象,但支持方式不同。
target:事件的目标
currentTarget:绑定事件的元素,与 'this' 的指向相同
stopPropagation() :取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法
stopImmediatePropagation(): 阻止监听同一事件的其他事件监听器被调用。
preventDefault(): 取消事件的默认行为,比如点击链接跳转。如果 cancelable 是 true,则可以使用这个方法
2.事件处理程序
DOM 0级事件处理程序
<div id="btn">
<script>
let btn = document.getElementById("btn")
btn.onclick = function(){
console.log('zxp')
}
btn.onclick = function(){
console.log('abc')
}
</script>
如上,即DOM 0级事件处理程序,将一个函数赋值给一个事件处理程序的属性,以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。要删除事件需将btn.onclick设置为null。
同一个dom元素,可以通过onclick添加多个事件,多个事件则会按照最后添加的事件输出,即'abc'。
DOM 2级事件处理程序
<div id="btn">
<script>
let btn = document.getElementById("btn")
btn.addEventListener("click",function(){
console.log('zxp')
},false)
btn.addEventListener("click",function(){
console.log('abc')
},false)
</script>
DOM 2级事件定义了addEventListener() 和 removeEventListener()两个方法,用于添加和删除事件处理程序的操作。
所有 DOM 节点都包含这两个方法,它们接受3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后的布尔值参数是 true 表示在捕获阶段调用事件处理程序,如果是 false(默认) 表示在冒泡阶段调用事件处理程序。
同一个dom元素,可以通过addEventListener()添加多个事件,多个事件则会按照它们的添加顺序触发,先输出'zxp'再输出'abc'。
通过 addEventListener()添加的事件处理程序只能使用removeEventListener()来移除,移除时传入的参数与添加时使用的参数相同。
IE 事件处理程序
IE通常都是特立独行的,它添加和删除事件处理程序的方法分别是:attachEvent() 和detachEvent(),同样接受事件处理程序名称与事件处理程序函数两个参数,但跟addEventListener()的区别是:
1.事件名称需要加“on”,比如“onclick”;
2.没了第三个布尔值,IE8及更早版本只支持事件冒泡;
3.仍可添加多个处理程序,但触发顺序是反着来的。
4.DOM0和DOM2级的方法,其作用域都是在其所依附的元素当中,attachEvent()则是全局,即如果使用this指向获取,访问到的就不是button元素,而是 window。
3.事件委托/事件代理
"事件委托"即是把原本需要绑定在子元素(比如li)的响应事件委托给父元素(比如ul),让父元素担当事件监听职务。事件委托的原理是基于事件传播过程中,逐层冒泡总能被祖先节点捕获 ,也就是DOM元素的事件冒泡。
一般为了简便,通常我们会直接在元素上绑定事件,通过其去触发,如下示例1,此时即使绑定都是同一个函数,但实质上每个li绑定的都是一个全新的函数,只不过这些函数的执行内容都是一致的,那么每个函数都需要开辟在内存中占据空间,一旦绑定事件过多,那么对于内存的开销是巨大的。因此,我通过将事件绑定到父元素上利用事件冒泡的原理来触发函数,同时规避产生过多相同函数占据内存的缺点,如示例2.
//示例1
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let liList = document.getElementByTagName("li");
for (let i = 0; i<liList.length;i++){
liList[i].onclick = function(){
console.log(i)
}
//liList[0].onclick !== liList[1].onclick
}
</script>
//示例2
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let ul = document.getElementByTagName("ul")[0];
ul.onclick = function(e){
let target = e.target || window.event //事件对象在ie8中要通过window.event才能取到,这里是做兼容处理
console.log(e.target || window.event)
//e.target 表示被点击的li,可以通过这种方式去拿到指定行的相关信息
}
</script>
4.阻止事件冒泡和默认事件
阻止事件冒泡
可以通过调用事件对象的 stopPropagation 方法,在任何阶段(捕获阶段或者冒泡阶段)中断事件的传播。此后,事件不会在后面传播过程中的经过的节点上调用任何的监听函数。调用 event.stopPropagation()不会阻止当前节点上此事件其他的监听函数被调用。如果你希望阻止当前节点上的其他回调函数被调用的话,你可以使用event.stopImmediatePropagation()方法。
<div id="btn">
<div id="btn1">
111111111111111111111111111111111111
<div id="btn2">
222222222222222222222222222222222222222222
<div id="btn3">
33333333333333333333333333333333
</div>
</div>
</div>
</div>
<script>
let btn1 = document.getElementById('btn1');
let btn2 = document.getElementById('btn2');
let btn3 = document.getElementById('btn3');
btn1.onclick = function aaaa() {
console.log('11111111111111111111111111111111111');
};
btn2.onclick = function bbbbb() {
console.log('2222222222222222222222222222');
};
btn3.onclick = function(event) {
console.log('333333333333333333333333333333');
event.stopPropagation()
//event.stopImmediatePropagation();
};
</script>
</div>
阻止默认事件
当特定事件发生的时候,浏览器会有一些默认的行为作为反应。最常见的事件比如link被点击,它会向上冒泡直到 DOM 结构的最外层 document,浏览器会解释 href 属性,并且在窗口中加载新地址的内容,但开发经常需要自行定义行为,为了达到这个目的,需要阻止浏览器的默认行为,这时候我们就需要调用 event.preventDefault()。
<a href="https://www.baidu.com/" id="baidu">百度</a>
<script>
document.getElementById('baidu').onclick = function() {
console.log('baidu');
// event.preventDefault();
};
</script>
最后
走过路过,不要错过,点赞、收藏、评论三连~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。