1. 程式人生 > >javascript 物件註冊自定義監聽器

javascript 物件註冊自定義監聽器

事件監聽的方式實現js 物件事件的訂閱/釋出。

eventEmitter 主要有三個介面方法:

  1. registe: 註冊事件監聽
  2. on: 訂閱事件
  3. emit: 釋出事件

使用示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <
meta
http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title> <script type="text/javascript" src="../bower_components/vue/dist/vue.min.js"></script> <script type="text/javascript" src="./eventEmitter.js"></script> </head> <body> <div
id="app">
<span v-text="message"></span> <button @click="bind">bind</button> <button @click="call">call</button> </div> <script> var component = Vue.extend({ el: '#app', data: function(){ return { message:
'Hello Vue.' } }, created(){ EventEmitter.registe(this) }, methods: { bind() { this.on('hello', function(evt){ console.log('hello ' + evt) }) }, call() { this.emit('hello', 'world') } } }) new Vue(component)
</script> </body> </html>

執行結果:

注意區分vue 自帶的$emit 和 $on

eventEmitter 原始碼如下:


;(function(global){

  /**
   * 遍歷執行陣列中的每個元素
   * @param {*} ary 
   * @param {*} func 
   */
  function each(ary, func){
    if (ary) {
      var i;
      for (i = 0; i < ary.length; i += 1) {
          if (ary[i] && func(ary[i], i, ary)) {
              break;
          }
      }
    }
  }

  /**
   * 遍歷執行物件中的每個屬性(不包含繼承鏈屬性)
   * @param {*} obj 
   * @param {*} func 
   */
  function eachProp(obj, func) {
    var prop;
    for (prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            if (func(obj[prop], prop)) {
                break;
            }
        }
    }
  }

  /**
   * 將source 物件屬性混入到target 中
   */
  function mixin(target, source, force, deepStringMixin) {
    if (source) {
      eachProp(source, function (value, prop) {
        if (force || !target.hasOwnProperty(prop)) {
          if (deepStringMixin && typeof value === 'object' && value &&
              !isArray(value) && !isFunction(value) &&
              !(value instanceof RegExp)) {

              if (!target[prop]) {
                  target[prop] = {};
              }
              mixin(target[prop], value, force, deepStringMixin);
          } else {
              target[prop] = value;
          }
        }
      });
    }
    return target;
  }

  /**
   * 判斷是不是方法
   * @param {*} target 
   */
  function isFunction(target){
    return Object.prototype.toString.call(target) === '[object Function]';
  }

  /**
   * 判斷是不是陣列
   * @param {*} target 
   */
  function isArray(target){
    return Object.prototype.toString.call(target) === '[object Array]';
  }

  var EventEmitter = {
    events: [],
    /**
     * 繫結事件
     * @param {*} name 
     * @param {*} cb 
     */
    on(name, cb){
      var cbs = this.events[name];
      if (!cbs) {
        cbs = this.events[name] = [];
      }
      cbs.push(cb);
    },
    /**
     * 觸發事件
     * @param {*} name 
     * @param {*} evt 
     */
    emit(name, evt){
      each(this.events[name], function (cb) {
        cb(evt);
      });
      if (name === 'error') {
          delete this.events[name];
      }
    }
  }

  var exp = {}
  exp.eventEmitter = EventEmitter;

  // 註冊事件監聽
  exp.registe = function(target){
    if(target.events || target.on || target.emit) throw new Error('target already has the mixin properties.');
    else {
      mixin(target, exp.eventEmitter)
    }
  }

  global.EventEmitter = exp;
})(window);

至此,結束。