0
点赞
收藏
分享

微信扫一扫

阻止事件继续传播

概念

我们知道,事件流分两个阶段,在捕获阶段,事件从最外层盒子传到最内层了;在冒泡阶段,事件从最内层

传到最外层。有没有办法阻止事件流传播呢?

我们可以使用 event.stopPropagation()来阻止事件继续传播。event 对象是任何事件处理函数中的事件

对象。

看一个例子:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Document</title>

<style type="text/css">

/* 样式表省略 */

</style>

</head>

<body>

<div class="box1" id="box1">

<div class="box2" id="box2">

<div class="box3" id="box3"></div>

</div>

</div>

<script type="text/javascript">

var box1 = document.getElementById("box1");

var box2 = document.getElementById("box2");

var box3 = document.getElementById("box3");

box1.addEventListener("click",function(){

alert("A");

},true);

box2.addEventListener("click",function(event){

event.stopPropagation();

alert("B");

},true);

box3.addEventListener("click",function(){

alert("C");

},true);

</script>

</body>

</html>

在页面上我们制作了三个盒子嵌套的结构,分别是外层盒子 box1、中层盒子 box2、内层盒子 box3。我们

分别监听了它们的捕获阶段的点击事件。

现在如果我们点击最内层盒子,按照正常情况,会依次弹出“A”、“B”、“C”,因为捕获阶段时,事件

从外层到内层传播。

但是现在我们在 box2 的事件处理函数中增加了 event.stopPropagation()语句,这句话的作用是阻止事

件继续传播。当 box2 的事件处理函数执行完毕之后,事件将不再往 box3 盒子传播。我们只会看见两个对话框

依次弹出:“A”、“B”,而不会看见“C”弹出。

我们使用 event.stopPropagation()切断了事件接续传播,那它在实战的时候有什么作用呢?我们来看具

体案例。

 举例:悬浮层

我们要制作一个悬浮层特效。所谓悬浮层指的是一个绝对定位的 div 盒子,它像系统对话框一样压盖住页

面的原有内容

我们不用实现非常复杂的页面布局,只需要用一个绝对定位的盒子模拟悬浮层即可,给它设置水平居中、垂

直居中。盒子定位完成之后,给它设置 display:none,此时盒子变的不可见。

在页面上放置一个按钮“显示悬浮层”,我们希望点击这个按钮后,能显示悬浮层。悬浮层显示之后,能够

点击页面任何地方(除在悬浮层上点击)关闭这个悬浮层。

HTML 结构非常简单,只有一个悬浮层盒子和一个按钮:

<div class="superposedlayer" id="superposedlayer"></div>

<button id="btn">显示悬浮层</button>

现在书写 JavaScript 代码,给按钮添加事件监听,让点击按钮之后悬浮层能够打开。

<script type="text/javascript">

var btn = document.getElementById("btn");

var superposedlayer = document.getElementById("superposedlayer");

//显示悬浮层

btn.onclick = function(event){

superposedlayer.style.display = "block";

}

</script>

程序非常简单,首先我们得到按钮和悬浮层。给按钮添加事件监听,当点击按钮之后,设置悬浮层的 display

属性为 block,此时悬浮层可见。

你会感觉编程非常简单,没有任何难度。但是,当我们实现“点击页面任何位置可以关闭悬浮层”会遇见一

定的挑战。代码如下:

<script type="text/javascript">

var btn = document.getElementById("btn");

var superposedlayer = document.getElementById("superposedlayer");

//显示悬浮层

btn.onclick = function(event){

superposedlayer.style.display = "block";

}

//关闭悬浮层

document.onclick = function(){

superposedlayer.style.display = "none";

}

</script>

我们给 document 对象增加了点击事件,document 对象表示整个文档,点击整个文档区域就会关闭悬浮层。

感觉程序很正确,但是此时你会发现,点击“显示炫富层”按钮失效了,悬浮层不能显示了。

这是因为,按钮的点击事件会冒泡到 document 对象上,也就是说,点击按钮的时候,也点击了 document。

此时按照事件传播的顺,会先执行按钮的点击事件即显示悬浮层的语句,然后执行 document 的点击事件即执行

关闭悬浮层。这就是为什么我们点击按钮什么事情也不会发生的原因了,悬浮层被显示,然后瞬间被关闭了。

解决办法就是设置当按钮响应事件后,阻止事件继续冒泡。只要事件不冒泡到 document 对象上,document

的 onclick 事件就不会执行。

代码如下:

//显示悬浮层

btn.onclick = function(event){

//阻止事件继续传播

event.stopPropagation();

superposedlayer.style.display = "block";

}

书写 event.stopPropagation()之后,会发现“弹出悬浮层”按钮又恢复正常了。

但是,程序并没有写完,因为我们又发现了一个 bug:在悬浮层内部点击的时候,悬浮层也被关闭了,这是

不符合预期的,因为用户总会在悬浮层内部进行内容的选择等操作,我们不能让用户在悬浮层内部点击的时候也关闭悬浮层。引发问题的原因非常简单:悬浮层的 onclick 事件冒泡到了 document 对象上。

解决方法就是设置悬浮层的点击事件,让它阻止事件继续传播,这样事件就不会传播到 document 对象上了。

案例的完整代码如下:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Document</title>

<style type="text/css">

.superposedlayer{

position: absolute;

width:600px;

height:300px;

background-color: orange;

top: 50%;

left:50%;

margin-left: -300px;

margin-top: -150px;

display: none;

overflow: hidden;

}

</style>

</head>

<body>

<div class="superposedlayer" id="superposedlayer"></div>

<button id="btn">显示悬浮层</button>

<script type="text/javascript">

var btn = document.getElementById("btn");

var superposedlayer = document.getElementById("superposedlayer");

//显示悬浮层

btn.onclick = function(event){

//阻止事件继续传播

event.stopPropagation();

superposedlayer.style.display = "block";

}

document.onclick = function(){

superposedlayer.style.display = "none";

}

superposedlayer.onclick = function(event){

//阻止事件继续传播

// event.stopPropagation();

}

</script>

</body>

</html>

举报

相关推荐

0 条评论