Web API —— DOM 学习(三)

目录

一、事件流

(一)事件流与两个阶段说明

1.事件捕获

2.事件冒泡

(二)阻止冒泡

(三)解绑事件 / 事件移除

1.level 0 的 DOM 语法

2.level 2 的 DOM 语法

鼠标经过事件的区别

(四)两种注册事件的区别

1.传统on注册( L0 )

2.事件监听注册( L1 )

二、事件委托

三、阻止默认行为

四、其他事件

(一)页面加载事件

1.事件名:load

2.事件名:DOMcontentLoaded

(二)页面滚动事件

1.基本使用

2.获取位置

(三)页面尺寸事件 

1.介绍

2.获得元素尺寸位置

client 方法

offset  方法

 getBoundingClientRect() 方法

练习:轮播图改良版

练习:页面滚动一定长度显示顶部栏



一、事件流

(一)事件流与两个阶段说明

事件流是指事件完整执行过程中的流动路径 就少访问那些标签是有一定流程的 不是写个 div 就直接访问的 div 标签的

包括捕获(从城市回村里——由大标签到小标签)和冒泡(从村里去城市——由小标签到大标签)

1.事件捕获

父亲到儿子 从DOM 的根元素开始执行对应的事件

要进行事件捕获要有对应的捕获值才能看到结果 就是下面第三个值

DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)

下面本来是 先儿子 再父亲 最后爷爷的顺序输出警示框

使用捕获机制后 先爷爷 再父亲 最后儿子 顺序变了(下面都是同名事件)

<body>
  <div class="father">
    <div class="son">
    </div>
  </div>
  <script>
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    }, true)
    fa.addEventListener('click', function () {
      alert('我是父亲')
    }, true)
    son.addEventListener('click', function () {
      alert('我是儿子')
    }, true)
  </script>
</body>
2.事件冒泡

儿子到父亲 当一个事件被触发时,它的祖先元素的同名事件会被依次触发

实际工作都是冒泡为主,把刚才捕获中的 第三个值去掉了就变成默认的冒泡方式了

事件冒泡是默认存在的

<body>
  <div class="father">
    <div class="son">
    </div>
  </div>
  <script>
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    })
    fa.addEventListener('click', function () {
      alert('我是父亲')
    })
    son.addEventListener('click', function () {
      alert('我是儿子')
    })
  </script>
</body>

[点击并拖拽以移动]
​

(二)阻止冒泡

有时候冒泡并不好容易导致事件影响父级元素,所以我们要阻止冒泡,

想把事件限制在当前元素内,就需要阻止冒泡

阻止事件冒泡需要提前拿到事件对象

语法:阻止流动传播(既能阻止冒泡也能阻止捕获)

e 别忘了 事件对象

<body>
  <script>
   事件对象.stopPropagation()
  </script>
</body>

下面本来应该按照事件冒泡方式的三个同名事件,结果在儿子那儿被阻断了 ,只显示我是儿子

<body>
  <div class="father">
    <div class="son">
    </div>
  </div>
  <script>
    const fa = document.querySelector('.father')
    const son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('我是爷爷')
    })
    fa.addEventListener('click', function () {
      alert('我是父亲')
    })
    son.addEventListener('click', function (e) {
      alert('我是儿子')
      e.stopPropagation()
    })
  </script>
</body>

(三)解绑事件 / 事件移除

解除不想要的事件

1.level 0 的 DOM 语法

解除事件后 下面点击按钮没反应

<body>
  <button>点击</button>
  <script>
    const btn = document.querySelector('button')
    btn.onclick = function () {
      alert('已点击')
    }
    btn.onclick = null
  </script>
</body>
2.level 2 的 DOM 语法

首先匿名函数无法解除事件

<body>
  <button>点击</button>
  <script>
    const btn = document.querySelector('button')
    function fn() {
      alert('已点击')
    }
    btn.addEventListener('click', fn)
    btn.removeEventListener('click', fn)
  </script>
</body>
鼠标经过事件的区别

mouseover 和 mouseout 有冒泡效果

一经过孩子 事件会冒泡到父亲上

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

(四)两种注册事件的区别

1.传统on注册( L0 )

同一个对象后面注册的事件会覆盖前一个事件(同一个事件)

可以用 null 覆盖实现事件的解绑

都是冒泡阶段执行 没有捕获阶段

2.事件监听注册( L1 )

语法: addEventListener(事件类型,事件处理函数,是否使用捕获)

后面不会覆盖前面注册的事件

可以冒泡也可以捕获 通过使用第三个参数使用

必须用 removeeventlistener(事件类型,事件处理函数,是否使用捕获) 来解绑事件

匿名函数无法解绑

二、事件委托

利用事件流的特征解决一些开发需求的知识技巧,可以减少注册次数,可以提高程序性能。

就是把事件委托给别人完成

给父亲注册事件,当我们触发子元素的事件时,会冒泡到父元素身上,从而触发父元素的事件

原理:利用了事件冒泡的特点

下面的例子:点击孩子 li 孩子没有点击事件 但是点击后事件会冒泡到父亲 ul 的事件上 所以会显示11

<body>
  <ul>
    <li>第1个孩子</li>
    <li>第2个孩子</li>
    <li>第3个孩子</li>
    <li>第4个孩子</li>
    <li>第5个孩子</li>
  </ul>
  <script>
   const ul = document.querySelector('ul')
   ul.addEventListener('click',function(){
    alert(11)
   })
  </script>
</body>

 事件委托当点击 li 标签时里面的文字变红,点击 p 标签时不变色 利用事件对象 e 的属性来控制

e 是 click 点击的对象 这样就能找到真正触发的事件对象

<body>
  <ul>
    <li>第1个孩子</li>
    <li>第2个孩子</li>
    <li>第3个孩子</li>
    <li>第4个孩子</li>
    <li>第5个孩子</li>
    <p>我不变色</p>
  </ul>
  <script>
    const ul = document.querySelector('ul')
    ul.addEventListener('click', function (e) {
      if (e.target.tagName === 'LI') {
        e.target.style.color = 'red'
      }
    })
  </script>
</body>

三、阻止默认行为

和阻止冒泡比较像,但是这个是阻止默认的行为,比如跳转标签,

下面的例子本,点击按钮会跳转到百度界面,但是添加了阻止默认行为 e.preventDefaule() 就不能再跳转到百度了直接没反应了

<body>
  <form action="http://www.baidu.com">
    <input type="submit" value="去百度">
  </form>
  <script>
    const form = document.querySelector('form')
    form.addEventListener('submit', function (e) {
      e.preventDefault()
    })
  </script>
</body>

四、其他事件

(一)页面加载事件

加载外部资源 如图片外联css Javascript 加载完毕后触发的事件

等页面资源全部加载完了再做一些事情。之前喜欢把 script 代码写在 head 中,这时直接找 dom 元素找不到

1.事件名:load

监听页面所有资源加载完毕:

window 比 document 还大

给 window 添加 load 事件就能监听 页面是否加载完毕

然后在函数里面添加 想要执行的内容

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    window.addEventListener('load', function () {
    })
  </script>
</head>
<body>
  
</body>
</html>
2.事件名:DOMcontentLoaded

和上一个不同之处在于 这个是监听所有 dom 元素加载完 速度快一点

document.addEventListener('DOMcontentLoaded', function(){

})

(二)页面滚动事件

1.基本使用

滚动条在滚动时持续触发的事件,想让用户滚动到某个区域时做一些动作,比如固定导航栏,返回顶部等。

事件名:scroll

下面例子一滚动就触发 打印我正在滚动,监听整个页面的滚动效果,就监听 window 对象

<body>
  <script>
    window.addEventListener('scroll',function(){
      console.log('我正在滚动')
    })
  </script>
</body>
2.获取位置

想要元素滚动的大小,就用这两个元素

scrollLeft:被卷去的头部 就是拉动滚动条 下面的文字会往上面移动 上面移出显示元素界面的部分就是,被卷去的头部

scrollTop:被卷去的左侧 同理

获得页面的 HTML 元素 不能通过 document.html 获取 而是 document.documentElement 获取 html 元素 它的 scrollTop 元素可以被赋值 就是 document.documentElement.scrollTop = 800 后面接数值 不加单位

这样就能拿到页面滚动的值了

<body>
  <script>
    window.addEventListener('scroll', function () {
      console.log(document.documentElement.scrollTop)
    })
  </script>
</body>

应用:让 div 盒子 在顶部被卷去大于等于 100px 时显示出来

<body>
  <div>
    我是一段文字我内容很多
    我是一段文字我内容很多
    我是一段文字我内容很多
    我是一段文字我内容很多
    我是一段文字我内容很多
    我是一段文字我内容很多
    我是一段文字我内容很多
  </div>
  <script>
    const div = document.querySelector('div')
    window.addEventListener('scroll', function () {
      let n = document.documentElement.scrollTop
      if (n >= 100) {
        div.style.display = 'block'
      } else {
        div.style.display = 'none'
      }
    })
  </script>
</body>

(三)页面尺寸事件 

1.介绍

在浏览器窗口尺寸改变时触发事件

事件语法:resize

<body>
  <div></div>
  <script>
    const div = document.querySelector('div')
    console.log(div.clientWidth)
    window.addEventListener('resize', function () {
      console.log(1)
    })
  </script>
</body>
2.获得元素尺寸位置
client 方法

获得元素宽高:不包含 border 边框 margin 也不包括 包含 padding

clientWidth

clientHight

offset  方法

offsetWidth

offsetHeight

这俩获得的元素自身的宽高包含 边框 得到的是数值有利于计算

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

offsetLeft 距左边边框的距离 如果父亲有定位则结果是距父亲的距离

offsetTop 元素是距最上面边框的距离 如果页面滚动了还是距原来页面最上面的距离


<body>
  <div></div>
  <script>
    const div = document.querySelector('div')
    console.log(div.offsetLeft)
  </script>
</body>
 getBoundingClientRect() 方法

也能得到盒子和边框的距离,但是这个方法对于整个页面来说是根据视口定位得到的距离,就是页面进行滚动时,这个方法得到的距离顶底和两侧的距离会发生变化,不是根据原来最开始的位置来计算的。

<body>
<div></div>
<script>
  const div = document.querySelector('div')
  console.log(div.getBoundingClientRect())
</script>
</body>

练习:轮播图改良版

界面展示:

创作活动

代码部分:
 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    .box {
      width: 400px;
      height: 200px;

    }

    .top {
      height: 50px;
    }

    .zuo {
      float: left;
      width: 160px;
      height: 50px;
      background-color: red;
    }

    ul {
      float: right;
      width: 240px;
      height: 50px;
      background-color: pink;
    }

    li {
      padding-right: 10px;
      width: 40px;
      float: right;
      list-style: none;
    }

    .bottom {
      height: 150px;
    }

    .box1 {
      float: left;
      width: 100px;
      height: 100%;

    }

    .box2 {
      float: left;
      width: 300px;
      height: 100%;

    }

    img {
      width: 100%;
      height: 100%;
    }

    .bottom {
      display: none;
    }

    .active {
      color: red;
    }

    .dong {
      display: block;
    }
  </style>
</head>
<div class="box">
  <div class="top">
    <div class="zuo">每日特价</div>
    <ul>
      <li><a class="active" href="#" data-id="0">精选</a></li>
      <li><a href="#" data-id="1">美食</a></li>
    </ul>
  </div>
  <div class="btm">
    <div class="bottom dong">
      <div class="box1"><img src="1.png" alt=""></div>
      <div class="box2"><img src="3.png" alt=""></div>
    </div>
    <div class="bottom">
      <div class="box1"><img src="2.png" alt=""></div>
      <div class="box2"><img src="4.png" alt=""></div>
    </div>
  </div>
</div>
<body>
  <script>
    const ul = document.querySelector('ul')
    ul.addEventListener('click', function (e) {
      if (e.target.tagName === 'A') {
        document.querySelector('ul .active').classList.remove('active')
        e.target.classList.add('active')
        const i = +e.target.dataset.id
        document.querySelector('.btm .dong').classList.remove('dong')
        document.querySelector(`.btm .bottom:nth-child(${i+1})`).classList.add('dong')
      }
    })
  </script>
</body>

</html>

练习:页面滚动一定长度显示顶部栏

界面展示:

代码部分:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      height: 3000px;
    }

    .header {
      position:fixed;
      top: -100px;
      width: 100%;
      height: 100px;
      background-color: red;
      text-align: center;
      line-height: 100px;
    }

    .neirong {
      overflow: hidden;
      height: 800px;
      background-color: pink;
      width: 80%;
      margin: 0 auto;
    }

    .sk {
      width: 200px;
      height: 100px;
      background-color: blue;
      margin-top: 200px;
    }
  </style>
</head>
<body>
  <div class="header">首页</div>
  <div class="neirong">
    <div class="sk"></div>
  </div>
  <script>
    const sk = document.querySelector('.sk')
    const neirong = document.querySelector('.neirong')
    const header  = document.querySelector('.header')
    document.addEventListener('scroll', function () {
   const n = document.documentElement.scrollTop
   if ( n >= sk.offsetTop ){
    header.style.top = 0
   }else{
    header.style.top = '-100px'
   }
    })
  </script>
</body>

</html>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值