DOM事件模型

103 阅读3分钟

目录

DOM事件概述

DOM事件机制

DOM事件特例

一、DOM事件概述

事件模型

浏览器的事件模型,就是通过监听函数对事件做出反应。事件发生后,浏览器监听到了这个事件,就会执行对应的监听函数。

事件的类型

事件类型主要分浏览器自带事件,和开发者自定义事件

二、DOM事件机制

1.事件绑定和删除

target.addEventListener 绑定事件的监听函数

target.removeEventListener 移除事件的监听函数

dispatchEvent() 触发事件

2.浏览器怎么知道有没有该元素有没有事件

e743aacbf62981c010491bb3a210847.png

  • 浏览器首先按 爷爷元素=>爸爸元素=>儿子元素的顺序看有没有函数监听

  • 然后再反向执行一遍顺序看有无函数监听

  • 如果有函数就调用,并提供事件信息,没有就跳过

  • 从外向内找监听函数,术语叫事件捕获

  • 从内向外找监听函数,术语叫事件冒泡 //工作最常用这个

  • 开发者自己选择把函数放在捕获阶段还是冒泡阶段

  • 为什么一件看起来差不多的事要来回做两次呢,看下文

3.事件绑定API

  • 关于事件绑定,IE5和网景公司有不同的机制标准

    1. IE5:目标.attachEvent('oncilck',fn) //冒泡机制

    2. 网景:目标.addEventListener('cilck',fn) //捕获机制

  • W3C最后统一了标准:目标.addEventListener('cilick',fn,bool)

    1. 如果bool不传值或为falsy

    • fn走冒泡机制,即当浏览器在冒泡阶段发现目标有fn监听函数,就调用,并提供事件信息

    1. 如果bool为true

    • 就让fn走捕获机制,当浏览器在捕获阶段发现目标有fn监听函数,就调用,并提供事件信息

aff37f93faf5834d764d5e5315bcf85.png

  • 捕获与冒泡

    1. 通俗的讲,捕获先调用爸爸的监听函数

    2. 冒泡先调用儿子的监听函数

    • 代码如下(只展示JS代码)
         const level1 = document.querySelector('.level1')
         const level2 = document.querySelector('.level2')
         const level3 = document.querySelector('.level3')
         const level4 = document.querySelector('.level4')
         const level5 = document.querySelector('.level5')
         const level6 = document.querySelector('.level6')
         const level7 = document.querySelector('.level7')
    
         let n = 1
    
         const removeX = (e) => {
             const t = e.currentTarget
             setTimeout(() => {
                 t.classList.remove('x')
             }, n * 1000)
             n += 1
         }
    
         const addX = (e) => {
             const t = e.currentTarget
             setTimeout(() => {
                 t.classList.add('x')
             }, n * 1000)
             n += 1
         }
         level1.addEventListener('click', removeX, true)
    
         level1.addEventListener('click', addX)
    
         level2.addEventListener('click', removeX, true)
    
         level2.addEventListener('click', addX)
    
         level3.addEventListener('click', removeX, true)
    
         level3.addEventListener('click', addX)
    
         level4.addEventListener('click', removeX, true)
    
         level4.addEventListener('click', addX)
    
         level5.addEventListener('click', removeX, true)
    
         level5.addEventListener('click', addX)
    
         level6.addEventListener('click', removeX, true)
    
         level6.addEventListener('click', addX)
    
         level7.addEventListener('click', removeX, true)
    
         level7.addEventListener('click', addX)
    
    • 效果

    1ux00-8a5g1.gif

    • 总结

      代码中bool值位true的事件为捕获,没有bool值的事件为冒泡

4.W3C事件模型

  • 默认的执行方式为:先捕获,再冒泡(可以阻止冒泡的过程)

  • 注意e对象被传递给所有监听函数

  • 事件结束后,我们可以认为e这个对象就不存在了

  • 如果确实在事件结束后需要e对象,可以提前把属性复制到自己的变量里,但最好不这么做

三、DOM事件特例

1. 假如只有一个div被监听(不考虑父子同时被监听)

  • 如果fn分别在捕获和冒泡阶段都要监听click事件

  • 并且用户点击的元素就是开发者所监听的

  • 那么捕获和冒泡谁先监听谁就先执行,这时个特例

2.取消冒泡

  • e.stopPropagation()这个api可以中断冒泡,让浏览器不再往上走

  • 一般用于封装某些独立的组件

3.不可以被取消冒泡的事件

  • 有一些事件不可以被取消冒泡

  • 需要了解的时候看MDN

da6c1850fcd7cae112096cbca810a5d.png

  • Bubbles 代表该事件是否冒泡

  • Cancelable 代表开发者是否能取消冒泡

4. 如何阻止滚动

  • scroll 事件不可取消冒泡

    1. 阻止scroll 默认动作没有用,因为是先有滚动这个动作才有滚动事件发生

    2. 要阻止滚动,可以先阻止whieeltouchstart的默认动作

    3. 但是要先找准滚动条所在的元素,不然没有效果

    4. 最后要用CSS让页面中的滚动条消失