<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      利用JavaScript自定義事件完成組件間的數據通信

      我們知道,在JavaScript中,原生DOM事件在開發中是很有用的(與用戶交互的重要方式),但是操作原生DOM事件其實有兩大缺點:性能低、依賴于瀏覽器(NodeJs、小程序等不可用)。那么這個時候,就需要我們進行自定義事件去處理某些特定的業務。

       

      認識Event對象及元素的dispatchEvent方法

      在JavaScript中,所有事件的父對象就是Event對象,也就是說像我們平時所有的點擊(click)、觸摸(touch)、鼠標等事件對象都繼承自Event。理解這一點是很重要的。先來簡單看一個事件的場景。

      場景一、頁面上有兩個按鈕a、b,當點擊按鈕b的時候,調用按鈕a的點擊事件。簡單布局代碼如下:

      <button id="btn1">a</button>
      <button id="btn2">b</button>
      

      程序員A的做法,分別獲取這兩個按鈕,然后給b按鈕添加點擊事件后,調用按鈕a的click方法。代碼如下:

      <button id="btn1" onclick="alert('I am a button named a')">a</button>
      <button id="btn2">b</button>
      <script>
          let btn1 = document.querySelector('#btn1');
          let btn2 = document.querySelector('#btn2');
          btn2.onclick = function(){
            btn1.onclick();
          }
      </script>
      

      程序員B的做法,分別獲取這兩個按鈕,然后給b按鈕添加點擊事件后,在回調函數中在添加按鈕a的點擊事件。代碼如下:

      <button id="btn1">a</button>
      <button id="btn2">b</button>
      <script>
          let btn1 = document.querySelector('#btn1');
          let btn2 = document.querySelector('#btn2');
          btn2.onclick = function(){
            btn1.addEventListener('click',function(){
              alert('I am a button named a')
            },false)
          }
      </script>
      

      看到這里,你認為誰的做法是正確的?顯然程序員A的做法是對的(就目前的要求來看),但有缺陷,如果按鈕a的事件是通過addEventListener方法去注冊監聽的,就不起作用了。那么該怎樣做才會比較好?這就需要我們的Event對象和元素的dispatchEvent方法了。改進代碼如下:

      <button id="btn1">a</button>
      <button id="btn2">b</button>
      <script>
          let btn1 = document.querySelector('#btn1');
          let btn2 = document.querySelector('#btn2');
          btn1.addEventListener('click',function(){
              alert('I am a button named a')
            },false)
          btn2.onclick = function(){
            let ev = new Event('click');
            btn1.dispatchEvent(ev);
          }
      </script>
      

      其中:

      • Event對象的構造函數需要一個參數,事件類型
      • dispatchEvent方法是將某個事件分發給某個元素

      認識自定義事件

      前面說過,在瀏覽器端javascript中,所有的事件都繼承自Event,那么其實要想實現一個自定義事件,也是需要繼承自Event。

      還是類似上面說過的場景,場景二:有兩個按鈕a,b,當調用b按鈕的點擊事件,怎么去觸發a按鈕上的自定義事件?

      <button id="btn1">a</button>
      <button id="btn2">b</button>
      <script>
          let a = document.querySelector('#btn1');
          let b = document.querySelector('#btn2');
          a.addEventListener('myClick',function(){
              alert('I am a button named a')
          },false)
          class MyEvent extends Event{
              constructor(...args){
                  super(...args);
                  this.a = 12;
              }
          }
          b.onclick = function(){
              const ev = new MyEvent('myClick');
              a.dispatchEvent(ev);
          }
      </script>
      

      這就是自定義事件的思想體現

      • 根據事件類型進行事件的注冊
      • 根據事件的類型分發對應的事件給需要者

      可以看出,對事件進行管理是很有必要,如Java中的EventBus、VueJs中的、emit等,將事件的監聽者及分發者抽象成一個獨立的模塊,來進行事件的管理(添加、移除等)有利用解耦。

      事件隊列完成組件間的通信

      這里可以把事件隊列想象成一根管道,類似前端gulp實現的核心思想(基于管道)、當使用者需要使用某個事件的時候,就在管道中注冊一個事件,然后通過該事件的類型,從管道中分發一個該類型的事件,在不需要使用后,還可以對相應的事件進行移除操作。代碼如下:

      class Pipe{
          constructor(){
              this.pipes = {};
          }
          /**
           * 注冊事件
           * @param {*} type 
           * @param {*} fn 
           */
          on(type,fn){
              this.pipes[type] = this.pipes[type] || [];
              if(this.pipes[type].findIndex(func => func==fn)==-1){
                  this.pipes[type].push(fn);
              }
          }
          /**
           * 移除事件
           * @param {*} type 
           * @param {*} fn 
           */
          off(type,fn){
              if(this.pipes[type]){
                  this.pipes[type] = this.pipes[type].filter((func) => func!==fn);
      
                  if(this.pipes[type].length===0){
                      delete this.pipes[type];
                  }
              }
          }
          /**
           * 分發事件
           * @param {*} type 
           * @param  {...any} args 
           */
          emit(type,...args){
              if(this.pipes[type]){
                  this.pipes[type].forEach((fn) => {
                      fn(...args);
                  })
              }
          }
      }
      

      場景:通過事件隊列模擬vuejs中組件間通信的實現。Component1負責對數據進行渲染,Component2中點擊按鈕,來改變Component1實例屬性a的值。代碼如下:

       
      <div id="box">
              {{a}}
      </div>
      <button id="btn1">++</button>
      <script>
          const $ = document.querySelectorAll.bind(document);
          let pipe = new Pipe();
          class Component1{
              constructor(){
                  this.a = 12;
                  this.el = $("#box")[0];
                  this.render();
                  pipe.on('add',(arg) => {
                      this.a+=arg;
                      this.render();
                  })
              }
      
              render(){
                  this.el.innerHTML = this.a;
              }
          }
      
          class Component2{
              constructor(){
                  this.el = $("#btn1")[0];
                  this.el.onclick = function(){
                      pipe.emit('add',12);
                  }
              }
          }
      
          new Component1();
          new Component2();
      </script>
      
      

      轉發至:https://segmentfault.com/a/1190000020550517?utm_source=tag-newes
      posted @ 2020-05-27 15:16  飛奔的龜龜  閱讀(390)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 天天做日日做天天添天天欢公交车| 亚洲av永久无码天堂影院| 亚洲成人av综合一区| 在线看免费无码av天堂的| 国内精品无码一区二区三区| 国产精品无码制服丝袜| 亚洲综合一区无码精品| 丰满人妻一区二区三区色| 久操线在视频在线观看| 成人拍拍拍无遮挡免费视频| 国产av综合色高清自拍| 国产精品福利中文字幕| 国产精品沙发午睡系列990531| 熟女人妻视频| 久久精品亚洲国产成人av| 日韩欧美一中文字暮专区| 亚洲人成人一区二区三区| 亚洲中文字幕无码不卡电影| 日韩一区国产二区欧美三区| 国产成人精品亚洲精品密奴| 久久精品国产福利一区二区 | 又黄又刺激又黄又舒服| 国产在线精彩自拍视频| 国产稚嫩高中生呻吟激情在线视频 | 久久月本道色综合久久| 国产麻豆成人精品av| 亚洲综合色一区二区三区| 国产成人一区二区三区免费| 久久精品无码中文字幕| 好日子在线观看视频大全免费动漫 | 亚洲精品国偷自产在线99人热| 人妻无码中文字幕| 国产原创自拍三级在线观看| 一区二区三区无码免费看| 国产一区二区亚洲一区二区三区| 国产一区二区三区九九视频| 日韩中文字幕高清有码| 欧洲精品码一区二区三区| 99久久99这里只有免费费精品| 国产日韩欧美| 天堂资源国产老熟女在线|