Webapis Dom事件进阶

本文详细探讨了WebAPIs中DOM事件的事件流,包括冒泡模式和捕获模式,以及如何阻止事件冒泡。介绍了事件委托的概念及其在提高程序效率中的应用,并讲解了页面加载和元素滚动事件的处理。此外,还讨论了如何获取和利用自定义属性、页面及元素尺寸的相关信息。
摘要由CSDN通过智能技术生成

事件流

事件流是对事件执行过程的描述,了解事件的执行过程有助于加深对事件的理解,提升开发实践中对事件运用的灵活度。

如果事件是在冒泡阶段执行的,我们称为冒泡模式,它会先执行子盒子事件再去执行父盒子事件,默认是冒泡模式。

如果事件是在捕获阶段执行的,我们称为捕获模式,它会先执行父盒子事件再去执行子盒子事件。

  1. addEventListener 第3个参数决定了事件是在捕获阶段触发还是在冒泡阶段触发

  2. addEventListener 第3个参数为 true 表示捕获阶段触发,false 表示冒泡阶段触发,默认值为 false

  3. 事件流只会在父子元素具有相同事件类型时才会产生影响

  4. 绝大部分场景都采用默认的冒泡模式(其中一个原因是早期 IE 不支持捕获)

<body>
  <h3>事件流</h3>
  <p>事件流是事件在执行时的底层机制,主要体现在父子盒子之间事件的执行上。</p>
  <div class="outer">
    <div class="inner"></div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')

    // 外层的盒子
    outer.addEventListener('click', function () {
      console.log('outer...')
    }, true) // true 表示在捕获阶段执行事件
    
    // 中间的盒子
    outer.addEventListener('click', function () {
      console.log('inner...')
    }, true)
  </script>
</body>

 

阻止冒泡

阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元素。

<body>
  <h3>阻止冒泡</h3>
  <p>阻止冒泡是指阻断事件的流动,保证事件只在当前元素被执行,而不再去影响到其对应的祖先元素。</p>
  <div class="outer">
    <div class="inner">
      <div class="child"></div>
    </div>
  </div>
  <script>
    // 获取嵌套的3个节点
    const outer = document.querySelector('.outer')
    const inner = document.querySelector('.inner')
    const child = document.querySelector('.child')

    // 外层的盒子
    outer.addEventListener('click', function () {
      console.log('outer...')
    })

    // 中间的盒子
    inner.addEventListener('click', function (ev) {
      console.log('inner...')

      // 阻止事件冒泡
      ev.stopPropagation()
    })

    // 内层的盒子
    child.addEventListener('click', function (ev) {
      console.log('child...')

      // 借助事件对象,阻止事件向上冒泡
      ev.stopPropagation()
    })
  </script>
</body>

 

鼠标经过事件:

mouseover 和 mouseout 会有冒泡效果

mouseenter 和 mouseleave 没有冒泡效果 (推荐)

<body>
    <div class="class">
        力锤敌阵<br>
        <button id="btn">如实天光破云</button>
    </div>
    <script>
        document.addEventListener('click', function () {
            console.log(10)
        })
        const box = document.querySelector('.class')
        const id = document.querySelector('#btn')
        box.addEventListener('click', function () {
            console.log(50)
        })
        id.addEventListener('click', function (e) {
            e.stopPropagation()
            console.log(100)
        })
        
    </script>
</body>


<body>
    <form action="">
        用户名: <input type="text" placeholder="请输入姓名"><br>
        密&emsp;码: <input type="password" placeholder="让尔等有命追无命回"><br>
        <input type="submit" value="如视天光破云">
        <script>
            const out = document.querySelector('form')
            out.addEventListener('submit', function (e) {
                e.preventDefault()
                alert('江东铁壁')
            })
        </script>
    </form>
</body>

 

 

  传统on注册(L0)
 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
 直接使用null覆盖偶就可以实现事件的解绑
 都是冒泡阶段执行的
  事件监听注册(L2)
 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
 后面注册的事件不会覆盖前面注册的事件(同一个事件)
 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
 匿名函数无法被解绑

 

事件委托

事件委托是利用事件流的特征解决一些现实开发需求的知识技巧,主要的作用是提升程序效率。

 

 事件对象中的属性 targetsrcElement属性表示真正触发事件的元素,它是一个元素类型的节点

<script>
  // 假设页面中有 10000 个 button 元素
  const buttons = document.querySelectorAll('table button')
  
  // 假设上述的 10000 个 buttom 元素共同的祖先元素是 table
  const parents = document.querySelector('table')
  parents.addEventListener('click', function (ev) {
    // console.log(ev.target);
    // 只有 button 元素才会真正去执行逻辑
    if(ev.target.tagName === 'BUTTON') {
      // 执行的逻辑
    }
  })
</script>
<script>
        // const li = document.querySelectorAll('li')
        // for (let i = 0; i < li.length; i++) {
        //     li[i].addEventListener('click', function () {
        //         console.log(2)
        //     })
        // }

       const ul = document.querySelector('ul')
    //    ul.addEventListener('click',function(){
    //     console.log(1)
    //    })
    // 减少事件注册的次数,提高代码的执行效率
    // 利用事件冒泡的原理,将事件委托给父元素
       ul.addEventListener('click',function(e) {
        if (e.target.tagName === 'LI') {
            console.log('ok')
        }
       })
    </script>

页面加载事件

加载外部资源(如图片、外联CSS和JavaScript等)加载完毕时触发的事件

有些时候需要等页面资源全部处理完了做一些事情

 

 

元素滚动事件

滚动条在滚动的时候持续触发的事件

<body>
    <div class="box">
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
        力摧敌阵,如视天光破云<br>
    </div>
    <script>
        const box = document.querySelector('.box')
        box.addEventListener('scroll',function(){
            console.log('它会更便宜')
        })
        document.addEventListener('scroll',function(){
            console.log('让尔等有命追无命回')
        })
    </script>

 

 自定义属性

<div class="box" id="box" data-box="哈哈哈" data-ou="电动机"></div>
    <script>
        const out = document.querySelector('#box')
        console.log(out.dataset.box)
        console.log(out.dataset.ou)
    </script>

页面尺寸事件

<script>
function setRemUnit() {
  // 获取 html  标签的宽度
  const w = document.documentElement.clientWidth 
  // 将 宽度 / 10 
  const rem = w / 10
  // 将其设置为 html 标签的 fontSize 
  document.documentElement.style.fontSize = rem + 'px'
}

setRemUnit()

// 当设备的窗口大小发生改变时 调用 setRemUnit 这个函数可以

window.addEventListener('resize', setRemUnit)
</script>

 

元素尺寸与位置

获取元素的自身宽高、包含元素自身设置的宽高、padding、border

offsetWidth和offsetHeight

获取出来的是数值,方便计算

注意: 获取的是可视宽高, 如果盒子是隐藏的,获取的结果是0

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值