4、DoM事件流 事件委托、绑定事件

一.绑定事件的方式

1. 事件绑定介绍

DOM(Document Object Model,文档对象模型)是针对HTML文档和XML(可扩展的标记语言)文档的一个API。DOM描绘了一个层次化的节点树,允许开发人员添加、移出和修改页面的某一部分,DOM脱胎于Netscape及微软公司创始的DHTML(动态HTML)。但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。
Netscape Navigator 4和IE4分别发布于1997年的6月和10月发布的DHTML,由于IE4和Netscape Navigator4分别支持不同的DHTML,为了统一标准,W3C开始制定DOM。1998年10月W3C总结了IE和 Navigator4的规范,制定了DOMLevel 1即DOM1,之前IE与Netscape的规范则被称为DOMLevel 0即DOM0。

  • Dom0
    • Dom0级事件具有极好的跨浏览器优势,会以最快的速度绑定。
    • 为某一个元素的同一个行为绑定不同的方法在行内会分别执行
    • 为某一个元素的同一个行为绑定不同的方法在script标签中后面的方法会覆盖前面的方法
    • 删除Dom0事件处理程序,只要将对应事件的属性设置为null即可
  • Dom1
    • Dom1一般只有设计规范没有具体实现,企业级应用无
  • Dom2
    • Dom2级事件是通过addEventListener绑定的事件,IE下的Dom2事件通过attachEvent绑定
    • 可以给某个元素的同一个行为绑定不同的方法在行内会分别执行
    • 删除Dom2事件处理程序通过removeEventListener
  • Dom3
    • Dom3级事件在Dom2级事件的基础上添加了更多的事件类型

2. DOML0绑定事件

a) 高版本浏览器绑定

  1. 语法:
    1. DOM对象.onclick = function() {}
  2. 特点:
    1. 不同事件类型会依次执行
    2. 相同事件类型会发生覆盖

b) 低版本浏览器绑定

  1. 语法:
    1. DOM对象.onclick = function() {}
  2. 特点:
    1. 不同事件类型会依次执行
    2. 相同事件类型发生覆盖

c) 高版本浏览器绑定多个相同事件

  1. 语法:
    1. DOM对象.onclick = funtion() {}
    2. DOM对象.onclick = function() {}

d) 低版本浏览器绑定多个相同事件

  1. 语法:
    1. DOM对象.onclick = funtion() {}
    2. DOM对象.onclick = function() {}

e) 总结

DOMLO绑定事件高低版本浏览器之间不存在任何的差异

3. DOML0解绑事件

a) 高版本浏览器解绑事件

  1. 语法
    1. DOM对象.onclick = null

b) 低版本浏览器解绑事件

  1. 语法
    1. DOM对象.onclick = null

4. DOML2绑定事件

a) 高版本浏览器绑定事件

  1. 语法:
    1. DOM对象.addEventListener(‘事件类型’, function(){});
    2. DOM对象.addEventListener(‘事件类型’, 函数名);
  2. 特点:
    1. 绑定多个事件会依次执行
    2. 绑定多个相同事件不会覆盖

b) 低版本浏览器绑定事件

  1. 语法:
    1. DOM对象.attachEvent(‘on事件类型’, function() {})
    2. DOM对象.attachEvent(‘on事件类型’, 函数名)
  2. 特点:
    1. 绑定多个事件会依次执行
    2. 绑定多个事件不会覆盖
    3. 绑定事件需要加on
    4. 低版本浏览器不支持addEventListener

5. DOML2解绑事件

a) 高版本浏览器解绑事件

  1. 语法:
    1. 回调函数设置为命名函数
    2. DOM对象.removeEventListener(‘事件类型’, 函数名)

b) 低版本浏览器解绑事件

  1. 语法:
    1. 回调函数设置为命名函数
    2. DOM对象.detachEvent(‘on事件类型’, 函数名)

6. 课堂案例

a) 封装绑定事件兼容性

image.png

二.事件流

1. 什么是事件流?

事件流是事件在执行过程中的一种自然现象,事件流包含3部分:

  1. 事件冒泡
  2. 事件捕获
  3. 处理程序(事件执行的代码)

事件流.png

2. 事件冒泡

a) DOML0事件冒泡

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
      .box {
         width: 300px;
         height: 300px;
         background-color: red;
      }
      .one {
         width: 200px;
         height: 200px;
         background-color: blue;
      }
  </style>
</head>
<body>
    <div class="box">
       <div class="one"></div>
    </div>
    <script>
       // DOML0实现冒泡
       var one = document.querySelector('.one');
       var box = document.querySelector('.box');
       one.onclick = function() {
          console.log('我是子元素被点击了');
       }
       box.onclick = function() {
          console.log('我是父元素被点击了');
       }
    </script>


</body>
</html>

b) DOML2事件冒泡

<body>
    <div class="box">
       <div class="one"></div>
    </div>
    <script>
       // DOML0实现冒泡
       var one = document.querySelector('.one');
       var box = document.querySelector('.box');
       one.addEventListener('click', function() {
          console.log('我是子元素被点击了');
       })
       box.addEventListener('click',function(){
          console.log('我是父元素被点击了');
       })
    </script>


</body>

c) 低版本浏览器事件冒泡

<body>
    <div class="box" id="box">
       <div class="one" id="one"></div>
    </div>
    <script>
       // DOML0实现冒泡
       var one = document.getElementById('one');
       var box = document.getElementById('box');
      
       one.attachEvent('onclick', function() {
          console.log('子元素被点击了');
       })


       box.attachEvent('onclick', function() {
          console.log('父元素被点击了');
       })
    </script>


</body>

总结:

  1. 事件冒泡是事件流中的默认现象
  2. onmouseover 会触发事件冒泡
  3. onmouseenter 不会触发事件冒泡

3. 事件捕获

a) DOML2事件捕获

<body>
  <div class="box" id="box">
    <div class="one" id="one"></div>
  </div>
  <script>
    // DOML0实现冒泡
    // DOML0实现冒泡
    var one = document.querySelector('.one');
    var box = document.querySelector('.box');
    one.addEventListener('click', function () {
      console.log('我是子元素被点击了');
    },true)
    box.addEventListener('click', function () {
      console.log('我是父元素被点击了');
    },true)
  </script>


</body>

注意:

  1. 只有高版本浏览器中DOML2方式才支持事件捕获
  2. DOML2方式第三个参数为true,代表事件捕获, 默认false代表事件冒泡

b) 总结

dom0事件及低级浏览器的dom2事件(没有第三个参数)都是只有冒泡,以后我们用的最多的也是冒泡,捕获几乎不用,高级浏览器的dom2事件可以根据第三个参数选择是捕获还是冒泡,一般我们都不写,默认是冒泡

4. 阻止事件冒泡

a) DOML0阻止事件冒泡

<body>
  <div class="box" id="box">
    <div class="one" id="one"></div>
  </div>
  <script>
    var one = document.querySelector('.one');
    var box = document.querySelector('.box');
    one.onclick = function (e) {
      console.log('我是子元素被点击了');
      // 阻止事件冒泡
      e.stopPropagation();
    }
    box.onclick = function (e) {
      console.log('我是父元素被点击了');
      // 阻止事件冒泡
      e.stopPropagation();
    }
  </script>


</body>

b) DOML2阻止事件冒泡

<body>
  <div class="box" id="box">
    <div class="one" id="one"></div>
  </div>
  <script>
    var one = document.querySelector('.one');
    var box = document.querySelector('.box');
    one.addEventListener('click', function (e) {
      console.log('我是子元素被点击了');
      // 阻止事件冒泡
      e.stopPropagation();
    })
    box.addEventListener('click', function (e) {
      console.log('我是父元素被点击了');
      // 阻止事件冒泡
      e.stopPropagation();
    })
  </script>


</body>

c) 低版本浏览器阻止事件冒泡

<body>
  <div class="box" id="box">
    <div class="one" id="one"></div>
  </div>
  <script>
    var one = document.querySelector('.one');
    var box = document.querySelector('.box');
    one.attachEvent('onclick', function(e) {
      console.log('我是子元素被点击了');
      // 阻止事件冒泡
      e.cancelBubble = true;
    }) 
      
    
    box.attachEvent('onclick',function (e) {
      console.log('我是父元素被点击了');
      // 阻止事件冒泡
      e.cancelBubble = true;
    })
  </script>


</body>

5. 拓展-阻止标签默认行为

a) 阻止表单提交默认跳转行为

<body>
  <form action="">
      <input type="text" name="uname">
      <input type="submit" class="btn">
  </form>
  <script>
      var btn = document.querySelector('.btn');
      btn.addEventListener('click', function(e) {
          console.log(123);
          // 阻止表单默认跳转
          e.preventDefault();
      })
  </script>


</body>

b) 阻止a标签点击跳转行为

<body>
  <form action="">
      <input type="text" name="uname">
      <input type="submit" class="btn">
  </form>
  <a href="">点我</a>
  <script>
      var a = document.querySelector('a');
      a.onclick = function(e) {
          console.log(123);
          e.preventDefault();

          // 或者
          // return false;
      }
  </script>
</body>

C) 总结

  1. 低版本浏览器DOML0事件写法中,阻止a标签默认行为通过 return false实现, 不支持preventDefault()
  2. 低版本浏览器DOML0事件写法中,阻止表单默认行为 通过 return false 实现,不支持preventDefault()
  3. 低版本浏览器DOML2事件写法中,阻止a标签和表单默认行为都是通过 return false实现

三.事件委托

1.什么是事件委托

事件委托: 本质上也是一种注册事件的方式,只不过没有将事件直接注册给事件源,而是给父元素注册了事件
注意:
事件委托(事件委派)中给父元素注册事件,该父元素不一定非得是直接父元素

2.什么时候使用事件委托

  1. 在任何时候注册事件都可以使用事件委托
  2. 如果页面中元素是动态创建且注册事件,强烈推荐使用事件委托实现(事件委托的重要应用场景)
  3. 事件委托可以减少代码量,提高程序执行效率

3.事件委托如何使用

a) 步骤

  1. 给当前事件源父元素注册事件
  2. 通过 事件对象参数.target 获取事件源
  3. 操作当前事件源

b) 事件委托实现核心

<body>
  <div class="box">
    <input type="button" value="按钮" class="btn">
  </div>
  <ul>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
  </ul>
  
  <script>
      // 正常注册事件通过委托
      var box = document.querySelector('.box');
      box.addEventListener('click', function(e) {
          console.log(e.target.value);
      });


      // 通过委托提供代码执行效率
      var lis =document.querySelectorAll('li');
      for(var i = 0; i < lis.length; i++) {
          lis[i].addEventListener('click', function() {
              console.log(this.innerHTML);
          })
      }


      var ul = document.querySelector('ul');
      ul.addEventListener('click', function(e){
          console.log(e.target.innerHTML);
      })



  </script>


</body>

<body>
  <div class="box">
    <input type="button" value="按钮" class="btn">
  </div>
  <ul>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
  </ul>
  
  <script>
      // 正常注册事件通过委托
      var box = document.querySelector('.box');
      box.addEventListener('click', function(e) {
          console.log(e.target.value);
      });


      // 通过委托提供代码执行效率
      var lis =document.querySelectorAll('li');
      for(var i = 0; i < lis.length; i++) {
          lis[i].addEventListener('click', function() {
              console.log(this.innerHTML);
          })
      }


      var ul = document.querySelector('ul');
      ul.addEventListener('click', function(e){
          console.log(e.target.innerHTML);
      })



  </script>


</body>

<body>
  <div class="box">
    <input type="button" value="按钮" class="btn">
  </div>
  <ul>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
  </ul>
  
  <script>
      // 正常注册事件通过委托
      var box = document.querySelector('.box');
      box.addEventListener('click', function(e) {
          console.log(e.target.value);
      });


      // 通过委托提供代码执行效率
      var lis =document.querySelectorAll('li');
      for(var i = 0; i < lis.length; i++) {
          lis[i].addEventListener('click', function() {
              console.log(this.innerHTML);
          })
      }


      var ul = document.querySelector('ul');
      ul.addEventListener('click', function(e){
          console.log(e.target.innerHTML);
      })



  </script>


</body>

<body>
  <div class="box">
    <input type="button" value="按钮" class="btn">
  </div>
  <ul>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
  </ul>
  
  <script>
      // 正常注册事件通过委托
      var box = document.querySelector('.box');
      box.addEventListener('click', function(e) {
          console.log(e.target.value);
      });


      // 通过委托提供代码执行效率
      var lis =document.querySelectorAll('li');
      for(var i = 0; i < lis.length; i++) {
          lis[i].addEventListener('click', function() {
              console.log(this.innerHTML);
          })
      }


      var ul = document.querySelector('ul');
      ul.addEventListener('click', function(e){
          console.log(e.target.innerHTML);
      })



  </script>


</body>

<body>
  <div class="box">
    <input type="button" value="按钮" class="btn">
  </div>
  <ul>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
      <li>我是li标签</li>
  </ul>
  
  <script>
      // 正常注册事件通过委托
      var box = document.querySelector('.box');
      box.addEventListener('click', function(e) {
          console.log(e.target.value);
      });


      // 通过委托提供代码执行效率
      var lis =document.querySelectorAll('li');
      for(var i = 0; i < lis.length; i++) {
          lis[i].addEventListener('click', function() {
              console.log(this.innerHTML);
          })
      }


      var ul = document.querySelector('ul');
      ul.addEventListener('click', function(e){
          console.log(e.target.innerHTML);
      })
  </script>


</body>

<script>
      // 正常注册事件通过委托
      var box = document.querySelector('.box');
      box.addEventListener('click', function(e) {
          console.log(e.target.value);
      });


      // 通过委托提供代码执行效率
      var lis =document.querySelectorAll('li');
      for(var i = 0; i < lis.length; i++) {
          lis[i].addEventListener('click', function() {
              console.log(this.innerHTML);
          })
      }


      var ul = document.querySelector('ul');
      ul.addEventListener('click', function(e){
          console.log(e.target.innerHTML);
      })
  </script>

c) 代码演示

<script>
      // 正常注册事件通过委托
      var box = document.querySelector('.box');
      box.addEventListener('click', function(e) {
          console.log(e.target.value);
      });


      // 通过委托提供代码执行效率
      var lis =document.querySelectorAll('li');
      for(var i = 0; i < lis.length; i++) {
          lis[i].addEventListener('click', function() {
              console.log(this.innerHTML);
          })
      }


      var ul = document.querySelector('ul');
      ul.addEventListener('click', function(e){
          console.log(e.target.innerHTML);
      })
  </script>

d) 注意事项

  1. 事件委托中需要重点理解 事件对象参数.target
    1. 事件对象参数.target 获取到的事件对象是用户实际点击的标签对象
    2. 事件对象参数.target 得到的是一个具体的DOM标签对象
  2. 一般在事件委托中,不会直接操作 事件对象参数.target,一般都加一个判断条件,确认用户点击的就是正确的标签,判断条件一般都通过标签名判断 **DOM对象.nodeName **

4.动画事件

webkitAnimationEnd 动画完成后执行的事件
webkitTransitionEnd 过渡动画执行完成后的事件

四.练习

1. 点击删除按

用户登录.gif

2. 统计学生信息

用户登录.gif

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值