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);

至此,结束。

猜你喜欢

转载自blog.csdn.net/Jacoh/article/details/85476724