Skip to content

事件冒泡和事件捕获 #20

@junfeisu

Description

@junfeisu

事件流

js中的事件流三个阶段:

  • 事件捕获(由外向内),就是从根元素逐层向里进行传播至最目标元素

  • 目标阶段,就是触发这个事件的最小粒度元素

  • 事件冒泡(由内向外),就是从目标元素逐层向外进行传播至根元素

先看一下事件捕获:

html:
    <div class="outer">
        <p class="inner">
            <span>123</span>
        </p>
    </div>

js:
    let outer = document.querySelector('.outer'),
        inner = document.querySelector('.inner'),
        span = document.querySelector('span')

    outer.addEventListener('click', () => console.log('outer 捕获'), true)
    inner.addEventListener('click', () => console.log('inner 捕获'), true)
    span.addEventListener('click', () => console.log('span 捕获'), true)

当点击span的时候,结果如图:

只绑定捕获阶段

再看一下事件冒泡:

html:
    <div class="outer">
        <p class="inner">
            <span>123</span>
        </p>
    </div>

js:
    let outer = document.querySelector('.outer'),
        inner = document.querySelector('.inner'),
        span = document.querySelector('span')

    outer.addEventListener('click', () => console.log('outer 冒泡'), false)
    inner.addEventListener('click', () => console.log('inner 冒泡'), false)
    span.addEventListener('click', () => console.log('span 冒泡'), false)

当点击span的时候,结果如图:

只绑定冒泡阶段

outer.addEventListener('click', () => console.log('outer 冒泡'), false)
inner.addEventListener('click', () => console.log('inner 冒泡'), false)
span.addEventListener('click', () => console.log('span 冒泡'), false)

outer.addEventListener('click', () => console.log('outer 捕获'), true)
inner.addEventListener('click', () => console.log('inner 捕获'), true)
span.addEventListener('click', () => console.log('span 捕获'), true)

结果如图所示:

同时绑定

同时绑定捕获和冒泡

当我们同时允许冒泡和捕获的时候就会发现其实一个完整事件流的顺序是这样的。当鼠标点击的时候,先从根元素开始向里层进行捕获,直至捕获到目标元素为止,这时进入到了目标阶段。再过渡到冒泡阶段,从目标元素一直冒泡到根元素

但是上面出现一个例外就是目标元素同时在捕获阶段和冒泡阶段绑定事件的时候,冒泡阶段的事件比捕获阶段先执行,具体原因我暂时也没查到,知道的同学欢迎告知。

当我们再上面的基础上再绑定DOM0级的事件处理函数

outer.addEventListener('click', () => console.log('outer 冒泡'), false)
inner.addEventListener('click', () => console.log('inner 冒泡'), false)
span.addEventListener('click', () => console.log('span 冒泡'), false)

outer.addEventListener('click', () => console.log('outer 捕获'), true)
inner.addEventListener('click', () => console.log('inner 捕获'), true)
span.addEventListener('click', () => console.log('span 捕获'), true)

outer.onclick = () => console.log('outer click')
inner.onclick = () => console.log('inner click')
span.onclick = () => console.log('span click')

结果如图所示:

加上DOM0的事件绑定

我们发现DOM0的事件默认是在冒泡阶段执行的。

这里再补充一点,event.stopPropagation()是用来阻止事件传播的,因为我们日常绑定的几乎都是在冒泡阶段执行,所以这个函数更多的时候被叫做阻止冒泡,也是可以用来阻止事件捕获的。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions