詳解JavaScript中的自定義事件編寫
來源:易賢網(wǎng) 閱讀:848 次 日期:2016-07-01 15:00:52
溫馨提示:易賢網(wǎng)小編為您整理了“詳解JavaScript中的自定義事件編寫”,方便廣大網(wǎng)友查閱!

這篇文章主要介紹了JavaScript中的自定義事件編寫,自定義事件是在瀏覽器中編寫Web頁面操作功能的基本方式,需要的朋友可以參考下

我們可以自定義事件來實現(xiàn)更靈活的開發(fā),事件用好了可以是一件很強大的工具,基于事件的開發(fā)有很多優(yōu)勢(后面介紹)。

與自定義事件的函數(shù)有 Event、CustomEvent 和 dispatchEvent。

直接自定義事件,使用 Event 構(gòu)造函數(shù):

var event = new Event('build');

// Listen for the event.

elem.addEventListener('build', function (e) { ... }, false);

// Dispatch the event.

elem.dispatchEvent(event);

CustomEvent 可以創(chuàng)建一個更高度自定義事件,還可以附帶一些數(shù)據(jù),具體用法如下:

var myEvent = new CustomEvent(eventname, options);

其中 options 可以是:

{

  detail: {

    ...

  },

  bubbles: true,

  cancelable: false

}

其中 detail 可以存放一些初始化的信息,可以在觸發(fā)的時候調(diào)用。其他屬性就是定義該事件是否具有冒泡等等功能。

內(nèi)置的事件會由瀏覽器根據(jù)某些操作進行觸發(fā),自定義的事件就需要人工觸發(fā)。dispatchEvent 函數(shù)就是用來觸發(fā)某個事件:

element.dispatchEvent(customEvent);

上面代碼表示,在 element 上面觸發(fā) customEvent 這個事件。結(jié)合起來用就是:

// add an appropriate event listener

obj.addEventListener("cat", function(e) { process(e.detail) });

// create and dispatch the event

var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}});

obj.dispatchEvent(event);

使用自定義事件需要注意兼容性問題,而使用 jQuery 就簡單多了:

// 綁定自定義事件

$(element).on('myCustomEvent', function(){});

// 觸發(fā)事件

$(element).trigger('myCustomEvent');

此外,你還可以在觸發(fā)自定義事件時傳遞更多參數(shù)信息:

$( "p" ).on( "myCustomEvent", function( event, myName ) {

 $( this ).text( myName + ", hi there!" );

});

$( "button" ).click(function () {

 $( "p" ).trigger( "myCustomEvent", [ "John" ] );

});

JavaScript 自定義事件就是有別于如 click, submit 等標(biāo)準事件的自行定制的事件,在敘述自定義事件有何好處之前,先來看一個自定義事件的例子:

<div id="testBox"></div>

// 創(chuàng)建事件

var evt = document.createEvent('Event');

// 定義事件類型

evt.initEvent('customEvent', true, true);

// 在元素上監(jiān)聽事件

var obj = document.getElementById('testBox');

obj.addEventListener('customEvent', function(){

  console.log('customEvent 事件觸發(fā)了');

}, false);

具體效果可以查看 Demo,在 console 中輸入 obj.dispatchEvent(evt),可以看到 console 中輸出“customEvent 事件觸發(fā)了”,表示自定義事件成功觸發(fā)。

在這個過程中,createEvent 方法創(chuàng)建了一個空事件 evt,然后使用 initEvent 方法定義事件的類型為約定好的自定義事件,再對相應(yīng)的元素進行監(jiān)聽,接著,就是使用 dispatchEvent 觸發(fā)事件了。

沒錯,自定義事件的機制如普通事件一樣——監(jiān)聽事件,寫回調(diào)操作,觸發(fā)事件后執(zhí)行回調(diào)。但不同的是,自定義事件完全由我們控制觸發(fā)時機,這就意味著實現(xiàn)了一種 JavaScript 的解耦。我們可以把多個關(guān)聯(lián)但邏輯復(fù)雜的操作利用自定義事件的機制靈活地控制好。

當(dāng)然,可能你已經(jīng)猜到了,上面的代碼在低版本的 IE 中并不生效,事實上在 IE8 及以下版本的 IE 中并不支持 createEvent(),而有 IE 私有的 fireEvent() 方法,但遺憾的是,fireEvent 只支持標(biāo)準事件的觸發(fā)。因此,我們只能使用一個特殊而簡單的方法觸發(fā)自定義事件。

// type 為自定義事件,如 type = 'customEvent',callback 為開發(fā)者實際定義的回調(diào)函數(shù)

obj[type] = 0;

obj[type]++;

obj.attachEvent('onpropertychange', function(event){

  if( event.propertyName == type ){

    callback.call(obj);

  }

});

這個方法的原理實際上是在 DOM 中增加一個自定義屬性,同時監(jiān)聽元素的 propertychange 事件,當(dāng) DOM 的某個屬性的值發(fā)生改變時就會觸發(fā) propertychange 的回調(diào),再在回調(diào)中判斷發(fā)生改變的屬性是否為我們的自定義屬性,若是則執(zhí)行開發(fā)者實際定義的回調(diào)。從而模擬了自定義事件的機制。

為了使到自定義事件的機制能配合標(biāo)準事件的監(jiān)聽和模擬觸發(fā),這里給出一個完整的事件機制,這個機制支持標(biāo)準事件和自定義事件的監(jiān)聽,移除監(jiān)聽和模擬觸發(fā)操作。需要注意的是,為了使到代碼的邏輯更加清晰,這里約定自定義事件帶有 'custom' 的前綴(例如:customTest,customAlert)。

/**

 * @description 包含事件監(jiān)聽、移除和模擬事件觸發(fā)的事件機制,支持鏈式調(diào)用

 *

 */

(function( window, undefined ){

var Ev = window.Ev = window.$ = function(element){

  return new Ev.fn.init(element);

};

// Ev 對象構(gòu)建

Ev.fn = Ev.prototype = {

  init: function(element){

    this.element = (element && element.nodeType == 1)? element: document;

  },

  /**

   * 添加事件監(jiān)聽

   * 

   * @param {String} type 監(jiān)聽的事件類型

   * @param {Function} callback 回調(diào)函數(shù)

   */

  add: function(type, callback){

    var _that = this;

    if(_that.element.addEventListener){

      /**

       * @supported For Modern Browers and IE9+

       */

      _that.element.addEventListener(type, callback, false);

    } else if(_that.element.attachEvent){

      /**

       * @supported For IE5+

       */

      // 自定義事件處理

      if( type.indexOf('custom') != -1 ){

        if( isNaN( _that.element[type] ) ){

          _that.element[type] = 0;

        } 

        var fnEv = function(event){

          event = event ? event : window.event

          if( event.propertyName == type ){

            callback.call(_that.element);

          }

        };

        _that.element.attachEvent('onpropertychange', fnEv);

        // 在元素上存儲綁定的 propertychange 的回調(diào),方便移除事件綁定

        if( !_that.element['callback' + callback] ){

          _that.element['callback' + callback] = fnEv;

        }

      // 標(biāo)準事件處理

      } else {

        _that.element.attachEvent('on' + type, callback);

      }

    } else {

      /**

       * @supported For Others

       */

      _that.element['on' + type] = callback;

    }

    return _that;

  },

  /**

   * 移除事件監(jiān)聽

   * 

   * @param {String} type 監(jiān)聽的事件類型

   * @param {Function} callback 回調(diào)函數(shù)

   */

  remove: function(type, callback){

    var _that = this;

    if(_that.element.removeEventListener){

      /**

       * @supported For Modern Browers and IE9+

       */

      _that.element.removeEventListener(type, callback, false);

    } else if(_that.element.detachEvent){

      /**

       * @supported For IE5+

       */

      // 自定義事件處理

      if( type.indexOf('custom') != -1 ){

        // 移除對相應(yīng)的自定義屬性的監(jiān)聽

        _that.element.detachEvent('onpropertychange', _that.element['callback' + callback]);

        // 刪除儲存在 DOM 上的自定義事件的回調(diào)

        _that.element['callback' + callback] = null;

      // 標(biāo)準事件的處理

      } else {

        _that.element.detachEvent('on' + type, callback);

      }

    } else {

      /**

       * @supported For Others

       */

      _that.element['on' + type] = null;

    }

    return _that;

  },

  /**

   * 模擬觸發(fā)事件

   * @param {String} type 模擬觸發(fā)事件的事件類型

   * @return {Object} 返回當(dāng)前的 Kjs 對象

   */

  trigger: function(type){

    var _that = this;

    try {

        // 現(xiàn)代瀏覽器

      if(_that.element.dispatchEvent){

        // 創(chuàng)建事件

        var evt = document.createEvent('Event');

        // 定義事件的類型

        evt.initEvent(type, true, true);

        // 觸發(fā)事件

        _that.element.dispatchEvent(evt);

      // IE

      } else if(_that.element.fireEvent){

        if( type.indexOf('custom') != -1 ){

          _that.element[type]++;

        } else {

          _that.element.fireEvent('on' + type);

        }

      }

    } catch(e){

    };

    return _that;

  }

}

Ev.fn.init.prototype = Ev.fn;

})( window );

測試用例1(自定義事件測試)

// 測試用例1(自定義事件測試)

// 引入事件機制

// ...

// 捕捉 DOM

var testBox = document.getElementById('testbox');

// 回調(diào)函數(shù)1

function triggerEvent(){

    console.log('觸發(fā)了一次自定義事件 customConsole');

}

// 回調(diào)函數(shù)2

function triggerAgain(){

    console.log('再一次觸發(fā)了自定義事件 customConsole');

}

// 封裝

testBox = $(testBox);

// 同時綁定兩個回調(diào)函數(shù),支持鏈式調(diào)用

testBox.add('customConsole', triggerEvent).add('customConsole', triggerAgain);

完整的代碼在 Demo。

打開 Demo 后,在 console 中調(diào)用 testBox.trigger('customConsole') 自行觸發(fā)自定義事件,可以看到 console 輸出兩個提示語,再輸入 testBox.remove('customConsole', triggerAgain) 移除對后一個監(jiān)聽,這時再使用 testBox.trigger('customConsole') 觸發(fā)自定義事件,可以看到 console 只輸出一個提示語,即成功移除后一個監(jiān)聽,至此事件機制所有功能正常工作。

更多信息請查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機網(wǎng)站地址:詳解JavaScript中的自定義事件編寫

2025國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)