javascript中的事件

一、 学习Javascript或者说是前端、那么学习和理解事件是非常重要的。因为我们写的js代码和html网页要进行交互、而交互的方式就是事件。
事件代表文档或浏览器窗口中某个有意义的时刻。可以使用仅在事件发生时执行的监听器(也叫处理程序)订阅事件。在传统软件工程领域,这个模型叫“观察者模式”,其能够做到页面行为(在 JavaScript 中定义)与页面展示(在 HTML 和 CSS 中定义)的分离。
浏览器的事情系统是比较复杂的、不同的浏览器对于不同的事件api有着不同的兼容。
二、事件流
在第四代 Web 浏览器(IE4 和 Netscape Communicator 4)开始开发时,两家开发团队碰到了一个有意思的问题:页面哪个部分拥有特定的事件呢?要理解这个问题,可以在一张纸上画几个同心圆。把手指放到圆心上,则手指不仅是在一个圆圈里,而且是在所有的圆圈里。两家浏览器的开发团队都是以同样的方式看待浏览器事件的。当你点击一个按钮时,实际上不光点击了这个按钮,还点击了它的容器以及整个页面。

事件流代表的是页面接收事件的顺序、IE 和 Netscape 开发团队提出了几乎完全相
反的事件流方案。IE 将支持事件冒泡流,而 Netscape Communicator 将支持事件捕获流。

1.事件冒泡:IE 事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。
2.事件捕获:。事件捕获的意思是最不具体的节点应该最先收到事件,而最具体的节点应该最后收到事件。事件捕获实际上是为了在事件到达最终目标前拦截事件。但事件捕获得到了所有现代浏览器的支持。实际上,所有浏览器都是从 window 对象开始捕获事件,而 DOM2 Events规范规定的是从 document 开始。由于旧版本浏览器不支持,因此实际当中几乎不会使用事件捕获。通常建议使用事件冒泡,特殊情况下可以使用事件捕获。

三 、事件流的阶段
DOM2 Events 规范规定事件流分为 3 个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,
为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个
阶段响应事件。所有现代浏览器都支持 DOM 事件流,只有 IE8 及更早版本不支持。

四 、事件处理程序

事情处理程序代表的是我们于网页交互的一个动作、我们为了响应这个动作必须调用一个函数、而这个 函数就是事件处理程序函数、事件处理程序函数以on开头、比如点击事件的事件 onclick。
绑定事件处理程序的方式主要有三种:

  1. html事件处理程序
 <button onclick="fn()">点击</button>
    <script>
      function fn(){
        console.log("html事件处理程序模式");
      }
  1. Dom0事件处理程序
    在 JavaScript 中指定事件处理程序的传统方式是把一个函数赋值给(DOM 元素的)一个事件处理程
    序属性。这也是在第四代 Web 浏览器中开始支持的事件处理程序赋值方法,直到现在所有现代浏览器
    仍然都支持此方法,主要原因是简单。要使用 JavaScript 指定事件处理程序,必须先取得要操作对象的
    引用。
    let btn = document.getElementsByTagName("button");
      console.log(btn);
      btn[0].onclick = function() {
        console.log("Dom0事件处理程序模式");
      };

3 .Dom2级事件处理程序
DOM2 Events 为事件处理程序的赋值和移除定义了两个方法:addEventListener()和 removeEventListener()。这两个方法暴露在所有 DOM 节点上,它们接收 3 个参数:事件名、事件处理函数和一个布尔值,true 表示在捕获阶段调用事件处理程序,false(默认值)表示在冒泡阶段调用事
件处理程序

      let btn = document.getElementsByTagName("button");
      console.log(btn);
      btn[0].addEventListener("click", () => {
       console.log('dom2级事件处理程序');
      }, true); 
       btn[0].addEventListener("click", () => {
         console.log('dom2级事件处理程序再次被触发');
      }, true); 

移除dom事件监听器

  let btn = document.getElementsByTagName("button");
      console.log(btn);
      function fn() {
        console.log("dom2事件");
      }
      btn[0].addEventListener("click", fn, false);

      btn[0].removeEventListener("click", fn, false);

五、事件对象
在 DOM 中发生事件时,所有相关信息都会被收集并存储在一个名为 event 的对象中。这个对象包
含了一些基本信息,比如导致事件的元素、发生的事件类型,以及可能与特定事件相关的任何其他数据。例如,鼠标操作导致的事件会生成鼠标位置信息,而键盘操作导致的事件会生成与被按下的键有关的信息。所有浏览器都支持这个 event 对象,尽管支持方式不同。

  <button>点击</button>
    <script>
      let btn = document.getElementsByTagName("button");
      console.log(btn);
      btn[0].onclick=function(e){
        console.log(`打印事件对象:${e}`); //如下图
      }
    </script>

在这里插入图片描述
在事件处理程序内部,this 对象始终等于 currentTarget 的值,而 target 只包含事件的实际目标。如果事件处理程序直接添加在了意图的目标,则 this、currentTarget 和 target 的值是一样的。下面的例子展示了这两个属性都等于 this 的情形:

    <button id="btn">点击</button>
    <script>
      let btn = document.getElementById("btn");
      btn.onclick = function (e) {
        console.log(e);
        console.log(this); //当前目标元素
        console.log(e.currentTarget); //当前目标元素
        console.log(e.target); //目标元素
      };
    </script>
     let btn = document.getElementById("btn");
      document.body.onclick = function (e) {
        console.log(e);
        console.log(this); //当前目标元素 body
        console.log(e.currentTarget); //当前目标元素body
        console.log(e.target); //目标元素target      //btn
      };

这段代码实际this指的是body因为它是当前的目标元素、而btn也能响应事件就是因为事件冒泡。

    <div id="div">
      <button id="btn">点击</button>
    </div>
    <script>
      let div = document.getElementById("div");
      //事件绑定在了div而button元素基于事件冒泡也能响应事件
       div.onclick = function (e) {
        console.log(e);
        console.log(this); //当前目标元素div
        console.log(e.currentTarget); //当前目标元素div
        console.log(e.target); //目标元素target   btn
      };
    </script>

下面代码阻止了事件流的传递导致后面的打印不会输出

   <div id="div">
      <button id="btn">点击</button>
    </div>
    <script>
      let btn = document.getElementById("btn");
      btn.onclick = function (event) {
        event.stopPropagation(); //阻止了事件流的传递、body里面的打印不会输出
        console.log("Clicked");
      };
      document.body.onclick = function (event) {
        console.log("Body clicked");
      };

事件的冒泡和捕获:
我们可以利用e.stopPagation()来阻止事件流的传递。

     let btn = document.getElementById("btn");
      let div=document.getElementById('div')
      document.body.addEventListener('click',(e)=>{
        console.log('222222');
        console.log(e.eventPhase);
      },false)
      div.addEventListener('click',(e)=>{
        e.stopPropagation()
        console.log('22222dwad2');
        console.log(e.eventPhase);
      },true)

六、事件委托

     <ul id="ul">
        <li id="a">1</li>
        <li id="b">2</li>
        <li id="c">3</li>
      
      </ul>
    </div>
    <script>
     let ul=document.getElementById('ul')
     ul.onclick=function(e){
        switch(e.target.id){
            case "a" :
               console.log("aaaaaaa");
              return;
            case "b" :
                console.log("bbbbbbb");
               return; 
             case "c" :
                console.log("Cccc");
                return;
             default :55555555
        }
     }
    </script>

上面代码其实就是用了事件委托的方式、我们直接给UL绑定事件、去点击每一个li都会触发冒泡事件。这样我们就不必给每一个li去绑定事件处理函数。

七、删除事件处理程序

把事件处理程序指定给元素后,在浏览器代码和负责页面交互的JavaScript 代码之间就建立了联系。这种联系建立得越多,页面性能就越差。除了通过事件委托来限制这种连接之外,还应该及时删除不用的事件处理程序。很多 Web 应用性能不佳都是由于无用的事件处理程序长驻内存导致的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值