<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件模型:捕获与冒泡</title>
    <style>
        div{
            border: 1px solid red;
            padding: 20px;
        }
    </style>
</head>
<body>
    <div id="grandfather">
        爷爷
        <div id="father">
            爸爸
            <div id="son">
                儿子
            </div>
        </div>
    </div>
    <script>
        son.addEventListener('click',function () {
            console.log('son')
        })
        father.addEventListener('click',function () {
            console.log('father')
        })
        grandfather.addEventListener('click',function () {
            console.log('grandfather')
        })
    </script>
</body>
</html>



image.png



当点击"儿子"区域时,会在控制台打出什么样的结果呢?首先,值得肯定的是,点击后,无论是"爸爸",还是"爷爷"都会触发"onclick"事件,只是执行的顺序应该是怎么样的呢?最先IE认为,执行的顺序应该是"爷爷"->''爸爸''->''儿子",这种执行顺序被称作 event capturing 。而Microsoft则不这样认为,他们认为先被点击的块具有执行优先权,所以触发事件的顺序应该是:"儿子"->''爸爸''->''爷爷'',这种执行的顺序则被称为: event bubbling。所以W3C为此做了标准,于是乎,W3C标准采取了所谓的"两全其美"的方案。事件模型中发生的任何事件,先从祖先元素一路向下开始捕获,直到达到目标元素,达到目标元素后开始冒泡,W3C事件模型如下:


image.png



如果想让执行的顺序是 event bubbling只需要:在DOM level2的event写法后添加一个 true即可:
       son.addEventListener('click',function () {
            console.log('son')
        },true)
        father.addEventListener('click',function () {
            console.log('father')
        },true)
        grandfather.addEventListener('click',function () {
            console.log('grandfather')
        },true)

当在事件最后加上个true后,在控制台打印的顺序为:"爷爷"->''爸爸''->''儿子"。当事件最后不写,或值为falsy时(0,'',null,undefined,NaN)时,则执行的顺序为事件冒泡顺序:

       son.addEventListener('click',function () {
            console.log('son')
        },false)
        father.addEventListener('click',function () {
            console.log('father')
        },false)
        grandfather.addEventListener('click',function () {
            console.log('grandfather')
        },false)

在控制台打印的顺序为:"儿子"->''爸爸''->''爷爷"。