【十】事件流

在这里插入图片描述

前言

本篇章主要讲述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>

最后

走过路过,不要错过,点赞、收藏、评论三连~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值