Blog

JavaScript 事件传播规则浅析

Cover Image for JavaScript 事件传播规则浅析
ZD
ZD

近来一直忙着一些有得没得的杂事,疏于打理个人博客,眨眼马上就要晃了两个月了,今天正好碰到一个问题,记录下来。

事情是这样的,对于JS的事件传播和事件默认行为的阻止一直像是隔着一层纱看风景,模模糊糊的。之前也碰到过几次类似的情况,由于强大的惰性,一直也没去彻底的追究一下传播的具体细节,今天呢,借着下面这个小例子,来学习一下事件的传播。

HTML

<!DOCTYPE html>
<html>
<head>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <meta charset="utf-8">
    <title>JS Bin</title>
</head>
<body>
    <input id="input" />
    <br/><br/>

    <div id="outer">
    <div id="inner">
    testline
    </div>
    </div>
</body>
</html>

CSS

#outer{
  background: #FEDDDD none;
  border: 1px solid #F30;
  padding: 20px;
}

#inner{
  background: #EEFF99 none;
  padding: 20px;
}

js

$(function(){
    var method1 = function(){
        $('#input').on('focus', function(){
            console.info('input focus')
        }).on('blur', function(){
            console.info('input blur')
        })

        $('#outer').click(function(e){
            console.info('outer clicked')
        })

        $('#outer').on('mousedown', function(e){
            console.info('outer mousedown')
        })

        $('#inner').on('click', function(e){
            console.info('inner clicked')
            e.stopPropagation();
        })

        $('#inner').on('mousedown', function(e){
            console.info('inner mousedown')
            e.preventDefault();
            e.stopPropagation();
        });
    }

    var method2 = function(){
        var outer = document.getElementById('outer');
        var inner = document.getElementById('inner');

        outer.addEventListener('mousedown', function(e){
            console.info('outer mousedown capture')
        }, true)

        outer.addEventListener('mousedown', function(e){
            console.info('outer mousedown bubble')
        }, false)

        inner.addEventListener('mousedown', function(e){
            console.info('inner mousedown capture')
        e.stopPropagation()
        }, true)

        inner.addEventListener('mousedown', function(e){
            console.info('inner mousedown bubble')
        }, false)
    }

    method2();
})

代码差不多就这些了,可以点击这里在线看看效果(注意打开console)。

假设你是了解一些JS的事件基本理论,比如事件的传播机制,冒泡和捕获等。

结论:

  1. 对keydown事件对象执行了preventDefault()之后,同一个对象上的click事件仍然会被触发。
  2. 对inner DIV 的 keydown 事件对象执行了 stopPropagation() 之后,outer DIV不再触发keydown,仍然会触发click事件
  3. 如果在outer DIV的捕获事件处理器中执行事件对象的 stopPropagation(),那么inner的 捕获事件处理器和冒泡事件处理器以及outer的冒泡事件处理器都不会被执行
  4. 通过阅读jquery2.1.1源码可知,jquery将事件处理器绑定在了冒泡阶段

题图来自 http://www.desktopwallpapers4.me/abstract/bubbles-20647/