浏览器 - 事件流

一、浏览器 事件

    1、事件流

        事件流 描述的是从页面中接受事件的顺序。事件流 分为两种: 事件捕获事件冒泡

 

    2、addEventListener

        EventTarget.addEventListener() 方法是将指定的监听器注册事件目标上,当该对象触发指定的事件时,指定的回调函数就会被执行

        事件目标可以是一个文档上的元素 ElementDocument和 Window 或者任何其他支持事件的对象。

    addEventListener() 有三个参数,

            第一个参数是事件类型,

            第二个参数是一个函数,作为事件触发的函数。

            第三个参数是一个布尔类型,是用来空值事件冒泡或者事件捕获的。 true: 事件捕获;false: 事件冒泡。第三个参数是可选的,默认是 false。

 

    3、事件捕获

        事件捕获 是Netscape团队提出的事件流。事件从最外层元素的事件开始,一级一级地传播到事件发生的具体元素。

        Example:

<body id="body">
	<div id="s1">
		s1
	    <div id="s2">s2</div>
	</div>

	<script>
	    s1.addEventListener("click",function(e) {
	        console.log("s1 捕获事件");
	    }, true);
	    s2.addEventListener("click",function(e) {
	        console.log("s2 捕获事件");
	    }, true);
	    body.addEventListener("click", function(e) {
	    	console.log("body级 捕获事件");
	    }, true)
	</script>
</body>

        点击 s2, 事件的执行顺序是: body -> S1 -> S2

 

    4、事件冒泡

       事件冒泡 是IE的事件流。 事件从事件开始的具体元素开始,一级一级朝着外部元素传播事件。

       我们拿上面的事件捕获的例子距离,我们只需要把addEventListener()的第三个参数修改成 false。

       Example:

 

<body id="body">
	<div id="s1">
		s1
	    <div id="s2">s2</div>
	</div>

	<script>
	    s1.addEventListener("click",function(e) {
	        console.log("s1 冒泡事件");
	    }, false);
	    s2.addEventListener("click",function(e) {
	        console.log("s2 冒泡事件");
	    }, false);
	    body.addEventListener("click", function(e) {
	    	console.log("body级 冒泡事件");
	    }, false)
	</script>
</body>

 

        点击 s2,事件的执行顺序:S2 -> S1 -> body

 

    5、DOM事件流

        "DOM2级事件" 事件总共分三个阶段:事件捕获阶段、目标阶段、事件冒泡阶段

                

 

Example:

 

<body>
    <div>
        <p id="parEle">
        	我是父元素    
        	<span id="sonEle">
        		我是子元素
				<span id="grandson">我是孙子元素</span>
        	</span>
        </p>
    </div>
</body>

<script type="text/javascript">
	var sonEle = document.getElementById('sonEle');
	var parEle = document.getElementById('parEle');

	parEle.addEventListener('click', function () {
	    console.log('父级 冒泡');
	}, false);
	parEle.addEventListener('click', function () {
	    console.log('父级 捕获');
	}, true);

	sonEle.addEventListener('click', function () {
	    console.log('子级冒泡');
	}, false);
	sonEle.addEventListener('click', function () {
	    console.log('子级捕获');
	}, true);
	grandson.addEventListener('click', function () {
	    console.log('孙子级冒泡');
	}, false);
	grandson.addEventListener('click', function () {
	    console.log('孙子级捕获');
	}, true);
</script>

        上面这个例子的执行顺序是: 父级捕获 -> 子集捕获 -> 孙子级冒泡 -> 孙子级捕获 -> 子级冒泡 -> 父级冒泡

        在捕获阶段又在冒泡阶段调用事件处理程序时:事件按DOM事件流的顺序执行事件处理程序。

        且当事件处于目标阶段时,事件调用顺序决定于绑定事件书写顺序

        像上面的例子,如果将 孙子级两个事件互换位置,那么就会先执行捕获事件,再执行冒泡事件

 

    阻止冒泡事件的方法: e.stopPropagation()

    阻止默认事件的方法: e.preventDefault()

 

    6、target vs currentTarget 的区别

        刚看到这个我查了一下。target 返回的是触发事件的元素,currentTarget 返回的是绑定事件的元素。

         但是这样看起来并不是很清晰,举个例子:

 

<body id="father" onclick="myFunction(event)">
    <p id="child" onclick="myFunction(event)">Click on child</p>
</body>

<script>
    function myFunction(event) { 
        console.log(`currentTarget: ${event.currentTarget.id}, target: ${event.target.id}`);
    }
</script>

 

        当点击child元素的时候,因为浏览器的冒泡事件先执行child元素的点击事件,之后执行 parent 元素的点击事件。

        事件的输出:

currentTarget: child, target: child

currentTarget: father, target: child

    可以看出,child 元素的点击事件中的 currentTarget target 都是 child 元素本身

        冒泡到 father 元素之后,当前执行绑定事件元素则变为 father,因此 currentTarget father;而触发事件的元素依旧是 child,所以 target 是 child

 

posted @ 2021-01-15 16:13  console.log('宇航')  阅读(188)  评论(0编辑  收藏  举报