perventDefault, stopPropagation, stopImmediatePropagation 三者的区别

event有三种特别容易混淆的方法, 用来阻止默认事件的发生

1.  e.preventDefault();

2. e.stopPropagation();

3. e.stopImmediatePropagation();

首先看这三个在MDN上的介绍

preventDefault: 如果当前event.cancelable属性为true, 则取消当前默认的动作, 但不阻止当前事件进一步传播.

stopPropagation: 阻止当前冒泡或者捕获阶段的进一步传播 .

stopImmediatePropagation: 阻止调用相同事件的其他监听器

1. e.preventDefault

下面一个例子, 当点击一个form中的 submit按钮提交表单时, 如果使用了 e.preventDefault , 就可以阻止表单提交

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>表单</title>
</head>
<body>
<form id="myForm" action="www.baidu.com" method="post">
    <div>
        <label for="name">姓名:</label>
        <input type="text" id="name" />
    </div>
    <div>
        <label for="mail">电子邮箱:</label>
        <input type="email" id="mail" />
    </div>
    <div>
        <label for="msg">消息:</label>
        <textarea id="msg"></textarea>
    </div>
    
    <div class="button">
        <button type="submit">发送你的消息</button>
    </div>
</form>
</body>
<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript">
    $('#myForm').on('submit', function(e) {
        e.preventDefault(); // 什么都不会发生
    });
</script>
</html>

此时使用e.preventDefault就能确保表单不会被提交, 但是他不能用来阻止来自冒泡阶段的submit或者点击事件, 下面两种方法就是为了解决这个问题的

注: 如果 Event 对象的 cancelable 属性是 fasle,那么就没有默认动作,或者不能阻止默认动作。无论哪种情况,调用该方法都没有作用。

2. e.stopPropagation

stopPropagation就是保证当前事件不在进一步冒泡

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>冒泡</title>
    <style type="text/css">
        .box1 {
            height: 400px;
            width: 400px;
            background: #f66;
        }
        .box2 {
            height: 300px;
            width: 300px;
            background: #6f6;
        }
        .box3 {
            height: 200px;
            width: 200px;
            background: #66f;
        }
    </style>
</head>
<body>
<div class="box1">
    1
    <div class="box2">
        2
        <div class="box3">3</div>
    </div>
</div>
</body>
<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript">
    $('.box1').on('click', function() {
        alert('ok');
    })
    $('.box2').on('click', function(e) {
        // e.preventDefault();
        e.stopPropagation(); // 点击box2不会反应
    })
    $('.box3').on('click', function(e) {
        // e.preventDefault();
        e.stopPropagation(); // 点击box3不会反应
    })
</script>
</html>

3. e.stopImmediatePropagation

以上两种方法已经解决了我们在处理事件中90%的问题, 接下来就介绍一种上面两种无法处理的情形

给一个标签添加两个 class, 一个是公共的class: item, 另一个是独有的class: element, 假设这两个class对当前网站的功能都很重要

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
</head>
<body>
    <div class="container">
        <a href="#" class="item element">点击</a>
    </div>
</body>
<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript">
    $('.item').on('click', function(e) {
        console.log('item 被点击了');
    });
    $('.element').on('click', function(e) {
        e.preventDefault(); // 此时链接不会跳转
        e.stopPropagation(); // 此时事件冒泡被阻止
        console.log('element 被点击了');
    });
</script>
</html>

当我们点击<a>标签时

这个现象会发生是因为item与element在DOM中是被平等对待的,与a标签点击冒泡到父级div不同, 我们点击同时出发了item与element的事件, 此时使用stopPropagation无法阻止这种事件

$('.element').on('click', function(e) {
        e.preventDefault(); // 此时链接不会跳转
        e.stopImmediatePropagation(); // item的点击事件将被阻止
        console.log('element 被点击了');
    });

    $('.item').on('click', function(e) {
        console.log('item 被点击了');
    });

 

原文链接

 

posted on 2018-04-18 09:44  sjpqy  阅读(1043)  评论(0编辑  收藏  举报

导航