19 事件高級

技術(shù)交流QQ群:1027579432,歡迎你的加入!

歡迎關注我的微信公眾號:CurryCoder的程序人生

1.注冊事件(綁定事件)

  • 注冊事件概述:給元素添加事件,稱為注冊事件綁定事件
  • 注冊事件有兩種方法:
    • 傳統(tǒng)方式
    • 方法監(jiān)聽注冊方式
  • 傳統(tǒng)方式:利用on開頭的事件onclick署拟,如下例所示:
    • 特點:注冊事件的唯一性
    • 同一個元素同一個事件只能設置一個處理函數(shù),最后注冊的處理函數(shù)將會覆蓋前面注冊的處理函數(shù)剩膘;
    <button>傳統(tǒng)注冊事件方式</button>
    <button>方法監(jiān)聽注冊事件</button>
    <script>
        var btns = document.querySelectorAll('button');
        btns[0].onclick = function() {
            alert('hi~');
        }     
        btns[0].onclick = function() {
            alert('hi old are you?');
        } 
    </script>
    
  • 方法監(jiān)聽注冊方式:w3c標準推薦方式;addEventListener()它是一個方法盆顾;IE9之前的IE不支持此方法怠褐,可使用attachEvent()代替。
    • 特點:同一個元素同一個事件可以注冊多個監(jiān)聽器您宪;
    • 按注冊順序依次執(zhí)行奈懒。
    • addEventListener()事件監(jiān)聽方式
      eventTarget.addEventListener(type, listener[, useCapture])
      
      • eventTarget.addEventListener()方法將指定的監(jiān)聽器注冊到eventTarget(目標對象)上,當該對象觸發(fā)指定的事件時宪巨,就會執(zhí)行事件處理函數(shù)磷杏。該方法接收三個參數(shù):
        • type: 事件類型字符串,如click捏卓、mouseover极祸、注意這里不要帶on
        • listener: 事件處理函數(shù),事件發(fā)生時遥金,會調(diào)用該監(jiān)聽函數(shù)峦椰;
        • useCapture: 可選參數(shù),是一個布爾值汰规,默認為false汤功,學完DOM事件流后再進一步學習。
      <button>傳統(tǒng)注冊事件方式</button>
      <button>方法監(jiān)聽注冊事件</button>
      <script>
          // 事件監(jiān)聽方式注冊事件
          btns[1].addEventListener('click', function() {
              alert('22');
          })
          btns[1].addEventListener('click', function() {
              alert('666');
          })
      </script>
      
    • attachEvent()事件監(jiān)聽方式:該方法了解即可溜哮!注意:IE8及早期版本支持滔金。
      eventTarget.attachEvent(eventNameWithOn, callback)
      
      • eventTarget.attachEvent()方法將指定的監(jiān)聽器注冊到eventTarget(目標對象)上,當該對象觸發(fā)指定的事件時茂嗓,指定的回調(diào)函數(shù)就會被執(zhí)行餐茵。該方法接收兩個參數(shù):
        • eventNameWithOn:事件類型字符串,如onclick述吸、onmouseover,這里要帶on忿族;
        • callback:事件處理函數(shù),當目標觸發(fā)事件時回調(diào)函數(shù)被調(diào)用蝌矛;
          <button>傳統(tǒng)注冊事件方式</button>
          <button>方法監(jiān)聽注冊事件</button>
          <button>IE9 attachEvent</button>
          <script>
          // attachEvent IE9以前的版本支持
          btns[2].attachEvent('onclick', function(){
              alert('IE9');
          })
          </script>
          
  • 注冊事件兼容性解決方案:處理兼容性的原則是先照顧大多數(shù)瀏覽器道批,再處理特殊瀏覽器。
    function addEventListener(element, eventName, fn) {
        // 判斷當前瀏覽器是否支持addEventListener方法
        if(element.addEventListener){
            element.addEventListener(eventName, fn);
        }else if(element.attachEvent){
            element.attachEvent('on' + eventName, fn);
        }else {
            // 相當于element.onclick = fn;
            element['on' + eventName] = fn;
        }
    }
    

2.刪除事件(解綁事件)

  • 刪除事件的方式
    • 傳統(tǒng)注冊方式:eventTarget.onclick = null;
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <script>
          var divs = document.querySelectorAll('div');
          divs[0].onclick = function() {
              alert('11');
              // 傳統(tǒng)方式刪除事件
              divs[0].onclick = null;
          }
      </script>
      
    • 方法監(jiān)聽注冊方式:eventTarget.removeEventListener(type, listener[, useCapture])與eventTarget.detachEvent(eventNameWithOn, callback);
      <div>1</div>
      <div>2</div>
      <div>3</div>
      <script>
          // 方法監(jiān)聽注冊方式刪除事件
          divs[1].addEventListener('click', fn); // 里面的fn不需要調(diào)用加小括號
          function fn() {
              alert('666');
              divs[1].removeEventListener('click', fn);
          }
      
          divs[2].attachEvent('onclick', fn1);
          function fn1() {
              alert('888');
              divs[2].detachEvent('onclick', fn1);
          }
      </script>
      
    • 刪除事件兼容性解決方案
      function removeEventListener(element, eventName, fn){
          // 判斷當前瀏覽器是否支持removeEventListener方法
          if(element.removeEventListener){
              element.removeEventListener(eventName, fn);
          }else if(element.detachEvent){
              element.detachEvent('on' + eventName, fn);
          }else{
              element['on' + eventName] = null;
          }
      }
      

3.DOM事件流

  • 事件流描述的是從頁面中接收事件的順序入撒。
  • 事件發(fā)生時會在元素節(jié)點之間按照特定的順序傳播隆豹,這個傳播過程即DOM事件流。例如茅逮,給一個div注冊了一個點擊事件:
    DOM事件流.png
  • DOM事件流分為三個階段
    • 1.捕獲階段(事件捕獲):網(wǎng)景最早提出璃赡,由DOM最頂層節(jié)點開始,然后逐級向下傳播到最具體的元素接收的過程献雅。
    • 2.當前目標階段
    • 3.冒泡階段(事件冒泡):IE最早提出碉考,事件開始時由最具體的元素接收,然后逐級向上傳播到DOM最頂層節(jié)點的過程挺身。
  • DOM事件流形象化理解:向水里扔一塊石頭侯谁,首先它會有一個下降的過程,這個過程可以理解為從最頂層向事件發(fā)生的最具體元素(目標點)的捕獲過程瞒渠;之后會產(chǎn)生泡泡良蒸,會在最低點(最具體元素)之后漂浮到水面上技扼,這個過程相當于事件冒泡伍玖。
    DOM事件流.png
  • 注意
    • js代碼中只能執(zhí)行捕獲或者冒泡其中的一個階段;
    • onclick和attachEvent只能得到冒泡階段剿吻;
    • addEventListener(type, listener[, useCapture])第三個參數(shù)如果是true窍箍,表示在事件捕獲階段調(diào)用事件處理程序;如果false(默認值),表示在事件冒泡階段調(diào)用事件處理程序椰棘。
    • 實際開發(fā)中我們很少使用時間捕獲纺棺,更關注事件冒泡
    • 有些事件是沒有冒泡的邪狞,如onblur祷蝌、onfocus、onmouseenter帆卓、onmouseleave等
    • 事件冒泡有時候會帶來麻煩巨朦,有時候又會幫助我們很巧妙的做某些事件,后面會介紹剑令。

4.事件對象

  • 官方解釋:event對象代表事件的狀態(tài)糊啡,如鍵盤按鍵的狀態(tài)、鼠標的位置吁津、鼠標按鈕的狀態(tài)等棚蓄。
  • 簡單理解:事件發(fā)生后,與事件相關的一系列信息數(shù)據(jù)的集合都放到這個對象中碍脏,這個對象就是事件對象event梭依,它有很多屬性和方法。
  • 比如:
    • 誰綁定了這個事件典尾;
    • 鼠標觸發(fā)事件的話睛挚,會得到鼠標的相關信息,如鼠標位置急黎。
    • 鍵盤觸發(fā)事件的話扎狱,會得到鍵盤的相關信息,如按下了哪個鍵勃教。
    <script>
        // 事件對象
        var div = document.querySelector('div');
        div.onclick = function(e) {
            console.log(e);
        //    兼容性處理方法
            e = e || window.event;
            console.log(e);
        }
    
        div.addEventListener('click', function(e){
            console.log(e);
        })
        // 1.event就是一個事件對象淤击,寫到我們監(jiān)聽函數(shù)的小括號中,當形參來看
        // 2.事件對象只有有了事件才會存在故源,它是系統(tǒng)給我們自動創(chuàng)建的污抬,不需要我們傳遞參數(shù)
        // 3.事件對象是我們事件的一系列相關數(shù)據(jù)的集合,根事件相關的绳军,比如鼠標點擊里面就包含了鼠標的相關信息印机,如鼠標坐標等信息。如果是鍵盤事件里面就包含了鍵盤事件的信息门驾,如判斷用戶按下了哪個鍵
        // 4.這個事件對象我們可以自己命名射赛,如event、evt奶是、e
        // 5.事件對象也有兼容性問題楣责,ie8以下瀏覽器通過window.event
    </script>
    
  • 事件對象的使用方法
    • 這個event是一個形參竣灌,系統(tǒng)幫我們設定為事件對象,不需要傳遞實參過去秆麸。
    • 當我們注冊事件時初嘹,event對象就會被系統(tǒng)自動創(chuàng)建,并依次傳遞給事件監(jiān)聽器(事件處理函數(shù))
    eventTarget.onclick = function(event){
        // 這個event就是事件對象沮趣,還可以寫成evt或e
    }
    eventTarget.addEventListener('click', function(event){
        // 這個event就是事件對象屯烦,還可以寫成evt或e
    })
    
  • 事件對象的兼容性方案
    • 事件對象本身的獲取存在兼容性問題:
      • 標準瀏覽器中是瀏覽器給方法傳遞的參數(shù),只需要定義形參e就可以獲取到房铭。
      • 在IE6~8中漫贞,瀏覽器不會給方法傳遞參數(shù),如果需要的話育叁,需要到window.event中獲取查找迅脐。
    • 解決方法:e = e || window.event;
  • 事件對象的常見屬性和方法
    事件對象的常見屬性和方法.png

5.阻止事件冒泡

  • 事件冒泡:開始時由最具體的元素接收,然后逐級向上傳播到DOM最頂層節(jié)點豪嗽。
  • 事件冒泡本身的特性谴蔑,會帶來壞處,也會帶來好處龟梦,需要我們靈活掌握隐锭。
  • 阻止事件冒泡的兩種方法
    • 標準寫法:利用事件對象中的stopPropagation()方法;具有兼容性問題计贰。
    • 非標準寫法:IE6~8利用事件對象的cancelBubble屬性钦睡;
  • 阻止事件冒泡的兼容性解決方案(了解)
    if(e && e.stopPropagation){
        e.stopPropagation();
    }else{
        window.event.cancelBubble = true;
    }
    

6.事件委托(代理、委派)

  • 事件冒泡本身的特性躁倒,會帶來壞處荞怒,也會帶來好處,需要我們靈活掌握秧秉。(好處是類似于生活中幫別人代拿快遞)
    <ul>
        <li>知否知否應是綠肥紅瘦</li>
        <li>知否知否應是綠肥紅瘦</li>
        <li>知否知否應是綠肥紅瘦</li>
        <li>知否知否應是綠肥紅瘦</li>
        <li>知否知否應是綠肥紅瘦</li>
    </ul>
    
  • 點擊每個li都會彈出對話框褐桌,以前需要給每個li注冊事件,是非常麻煩的象迎。而且訪問DOM次數(shù)越多荧嵌,就會延長整個頁面的交互就緒時間。
  • 事件委托:也稱為事件代理砾淌,在jQuery中稱為事件委派啦撮。
  • 事件委托的原理:不是每個子節(jié)點單獨設置事件監(jiān)聽器,而是事件監(jiān)聽器設置在其父節(jié)點上汪厨,然后利用事件冒泡原理影響設置每個子節(jié)點赃春。
  • 以上案例的解決方法:給ul注冊點擊事件,然后利用事件對象的target來找到當前點擊的li骄崩。因為點擊li聘鳞,事件會冒泡到ul上薄辅,ul有注冊事件要拂,就會觸發(fā)事件監(jiān)聽器抠璃。
  • 事件委托的作用:只操作了一次DOM,提高了程序的性能脱惰。

7.常見的鼠標事件

常見的鼠標事件.png

%7CimageView2/2/w/1240)

  • 禁止鼠標右鍵菜單:contextmenu主要控制應該何時顯示上下文菜單搏嗡,主要用于程序員取消默認的上下文菜單。
    document.addEventListener('contextmenu', function(e){
        e.preventDefault();
    });
    
  • 禁止鼠標選中(selectstart開始選中)
    document.addEventListener('selectstart', function(e){
        e.preventDefault();
    });
    
  • event對象代表事件的狀態(tài)拉一,根事件相關的一系列信息的集合采盒。目前,我們主要是用鼠標事件對象MouseEvent和鍵盤事件對象keyboardEvent蔚润。
  • 鼠標事件對象MouseEvent
    鼠標事件對象.png

8.常見的鍵盤事件

  • 事件除了使用鼠標觸發(fā)磅氨,還可以使用鍵盤觸發(fā)。


    常見的鍵盤事件.png
  • 注意
    • 如果使用addEventListener不需要加on嫡纠;
    • onkeypress和前面2個的區(qū)別是烦租,它不能識別功能鍵,如左右箭頭除盏、shift叉橱、ctrl鍵;
    • 三個事件的執(zhí)行順序是:keydown --> keypress --> keyup
  • 鍵盤事件對象keyboardEvent
    keyCode屬性.png
  • 注意:
    • onkeydown和onkeyup不區(qū)分字母大小寫者蠕,onkeypress區(qū)分字母大小寫窃祝;
    • 在實際開發(fā)中,更多使用的是keydown和keyup踱侣,它能識別所有的鍵(包括功能鍵)粪小;

9.資料下載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抡句,一起剝皮案震驚了整個濱河市糕再,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玉转,老刑警劉巖突想,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異究抓,居然都是意外死亡猾担,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門刺下,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绑嘹,“玉大人,你說我怎么就攤上這事橘茉」ひ福” “怎么了姨丈?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長擅腰。 經(jīng)常有香客問我蟋恬,道長,這世上最難降的妖魔是什么趁冈? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任歼争,我火速辦了婚禮,結(jié)果婚禮上渗勘,老公的妹妹穿的比我還像新娘沐绒。我一直安慰自己,他們只是感情好旺坠,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布乔遮。 她就那樣靜靜地躺著,像睡著了一般取刃。 火紅的嫁衣襯著肌膚如雪蹋肮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天蝉衣,我揣著相機與錄音括尸,去河邊找鬼。 笑死病毡,一個胖子當著我的面吹牛濒翻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啦膜,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼有送,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了僧家?” 一聲冷哼從身側(cè)響起雀摘,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎八拱,沒想到半個月后阵赠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡肌稻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年清蚀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爹谭。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡枷邪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诺凡,到底是詐尸還是另有隱情东揣,我是刑警寧澤践惑,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站嘶卧,受9級特大地震影響尔觉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脸候,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一穷娱、第九天 我趴在偏房一處隱蔽的房頂上張望绑蔫。 院中可真熱鬧运沦,春花似錦、人聲如沸配深。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽篓叶。三九已至烈掠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缸托,已是汗流浹背左敌。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留俐镐,地道東北人矫限。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像佩抹,于是被迫代替她去往敵國和親叼风。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348