jquery
之因此成爲最受歡迎的前端庫,很大一部分是得益於它的事件具備良好的語義,優秀的兼容性,而且便於管理和擴展。javascript
在這裏我會介紹 jquery
事件的一些比較基礎的用法。html
jquery
事件脫胎於瀏覽器的 addEventListener (W3)
和 attachEvent (IE)
方法 , 提供了跨瀏覽器的一致性API。具體的實現原理能夠參考Aaron的系列文章
jquery源碼分析-事件。前端
jquery
中實現事件綁定有多種方式,其中 $(selector).event(func)
方式中 event
支持一系列的瀏覽器事件,文檔加載事件,表單事件,鍵盤事件和鼠標事件,但並不是所有。java
// 經常使用的寫法 $('body').click(function(){ }) $('body').on('click',function(){ }) $('body').one('click',function(){ }) // 只會執行一次,而後銷燬事件 // 其餘寫法(不推薦) $('body').bind('click',function(){ }) $('body').delegate('p','click',function(){ }
on.('click')
和 .click()
的區別。on
屬於 綁定事件處理器
(event-handler-attachment
) , 而 .click()
屬於 jquery
包裝好的鼠標事件。jquery
on
能夠綁定dom和bom的既有事件,也能夠綁定自定義的事件。因此推薦始終只使用$(selector).on(event,func)
的方式,彈性的綁定更多的事件:瀏覽器
$(document).hashchange(function(){ })// 報錯,jquery沒有提供此事件處理器 $(document).on('hashchange',function(){ })// 綁定事件成功
也能夠同時綁定多個事件處理同一事務:less
$('input').on('focus input',function(){ })// 在文本框聚焦和輸入的時候,都作一樣的事情
或者是綁定多個事件處理不一樣事務:dom
$('input') .on('focus',function(){ })// 聚焦時處理 .on('blur',function(){ })// 失去焦點時處理 .on('input',function(){ })// 輸入時處理
根據綁定事件方式的不一樣,解除事件也有好幾種方式。
推薦始終使用 $(selector).off(event)
的方式解除事件綁定,由於 on/off
正好構成了一個開關。函數
/* * 能夠解除 $.click(func),$.on('click',func)和 $.bind('click',func) 綁定的事件, * 不能解除delegate方式綁定的事件 */ $('body').off('click') // 同上 $('body').unbind('click') // 只能解除 delegate方式綁定的事件 $('body').undelegate('p','click')
在 jquery
中,有許多方法根據其參數個數的不一樣,既能夠是賦值,也能夠作爲取值操做。
事件也不例外,許多時候能夠利用這個特性,代替手動去觸發一些事件,如下示例中的兩種方式,均可以實現自動觸發事件。源碼分析
// (當表單字段未經過驗證時) 自動選中文本值 $('input').select() $('input').trigger('select') // 觸發已有的點擊事件 $(selector).click() $(selector).trigger('click') // 經過觸發事件,通知select2插件從新渲染 $('select').change() $('select').trigger('change')
事件委託經過事件從目標元素冒泡到根元素的原理實現,它有2個好處,一是大幅下降事件綁定的內存佔用,二是能夠對後來加入的元素生效。
// 寫法 $(selector).on(event, selector2, func) // 不推薦的方法 $(selector).delagate(selector2, event, func)
事件委託原理及性能分析詳見 解密jQuery事件核心 - 委託設計(二)
上面列舉了一些簡單的事件綁定,解綁和委託的使用,下面會說到一些更加個性化的用法。
event.preventDefault()
這個方法用於阻止瀏覽器的默認行爲,一般用於表單提交或是頁面滾動。
$('form').on('submit',function(event){ // 阻止了默認的表單提交事件,下面能夠作一些愛作的事情了 event.preventDefault(); }) $(document).on('touchmove',function(event){ // 阻止了瀏覽器的默認滾動,也能夠作些愛作的事情了 event.preventDefault(); })
阻止事件傳播即阻止事件繼續向上冒泡。
// 點擊div時,會依次alert 2 ,1 $('body').on('click',function(){alert(1)}) $('div').on('click',function(){alert(2)}) // 下面的代碼只會alert一個 2,由於事件中止冒泡了,不會被body監聽到 $('body').on('click',function(){alert(1)}) $('div').on('click',function(event){ event.stopPropagation(); alert(2) })
除了阻止默認的事件,中止向上冒泡以外,有時還須要禁止後續的事件執行,可使用 event.stopImmediatePropagation()
方法。該方法會自動調用 event.stopPropagation()
方法。
// 不使用 event.stopImmediatePropagation() 將會alert 2,3,4,1 // 加上以後只會alert 2 $('body').on('click',function(){alert(1)}) $('div').on('click',function(event){ event.stopImmediatePropagation(); alert(2) }) $('div').on('click',function(){ alert(3) }) $('div').on('click',function(){ alert(4) })
想要更精準的控制事件,不少時候還須要利用 jquery
的命名空間機制。
$('div').on('click.click1',function(){console.log(1)}) $('input').on('click.click1',function(){console.log(11)}) $('div').on('click.click2',function(){console.log(2)}) $('input').on('click.click2',function(){console.log(21)}) // 只觸發click2事件 $('div,input').trigger('.click2') // 解除click1事件,click2任然會執行 $('div,input').off('.click1')
把多個事件組合起來,或者在特定條件下觸發事件,普通的事件綁定是沒法知足須要的,能夠經過自定義事件來造成 pub-sub
組合。
好比監聽 短信驗證碼發送倒計時:
// 僞代碼 setInterVal(function(){ time--; if(time < 1){ $('.js-timeless-button').trigger('time-end', params0, params1); } },1000) // 自定義事件回調函數默認第一個參數爲event對象,之後的參數依次是傳入的參數 $('.js-timeless-button').on('time-end',function(event, params0, params1){ });
或者是 頁面滾動到了底部
// 僞代碼 $(window).on('scroll',function(){ if((($(window).scrollTop() + $(window).height())) >= $(document).height()){ $(document).trigger('infinite', params0, params1); } }) $(document).on('infinite',function(event, params0, params1){ });
解除自定義事件和解除其餘事件的方式相同。能夠經過 off
或者 unbind
進行。
在 jquery
中,事件是按照其綁定順序依次執行的。若是想要調整執行順序,或是禁止以前綁定的方法發生,能夠經過重寫事件隊列的方式。
查看某個dom上已綁定事件的方法是$._data(elem,'events')
(jquery
版本>1.7)。
elem
是 dom對象
而非 jquery對象
。
function alertBottle(){ $("body").on('click',function() { alert("1") }); $("body").on('click',function() { alert("2") }); $("body").on('click',function() { alert("3") }); } // 點擊body會依次alert 1, 2, 3 alertBottle(); // 倒序執行 alertBottle(); var Events = $._data($("body").get(0),'events'); Events.click.sort(function(a,b){return b.guid-a.guid }) // 禁止執行以前的一切, 只執行我 alertBottle(); var Events = $._data($("body").get(0),'events'); Events.click = null; $("body").on('click',function() { alert("4") }); // 最早執行我 alert 4, 1, 2, 3 alertBottle(); $("body").on('click',function() { alert("4") }); var Events = $._data($("body").get(0),'events'); var last = Events.click.pop(); Events.click.unshift(last);
兼容jquery低版本的寫法是:
$.fn.getEvents = function() { if (typeof(jQuery._data) == 'function') { return jQuery._data(this.get(0), 'events') || {}; } else if (typeof(this.data) == 'function') { // jQuery version < 1.7.? return this.data('events') || {}; } return {}; }; // 使用 $("body").getEvents();
參考資料:jquery中文文檔