天下之事,必先处之难,而后易之。

JS事件派发器EventEmitter

原文地址:http://zhangyiheng.com/blog/articles/js_event_mitter.html

需求

随着Browser客户端JS越来越复杂,MVC(Client端)设计模式成为一个很好的开发选择, 而MVC开发模式中,最基础的功能就是把Model和View关联起来, 当Model发生变化的时候,View呈现做出相应的调整。

实现此功能最合适的方式莫过于事件Event了, 对于Event大家应该都很熟悉,比如dom中的button,可以通过addEventListener/attachEvent添加click事件处理。

而一般的object对象是没有事件派发功能的,基于此需求,实现了一个EventEmitter。

 

具体实现

复制代码
/**
  * Created by taozh on 2017/6/22.
  * taozh1982@gmail.com
  */
 var EventEmitter = function () {
     this.__z_e_listeners = {};
 };
 EventEmitter.prototype.on = function (evt, handler, context) {
     var handlers = this.__z_e_listeners[evt];
     if (handlers === undefined) {
         handlers = [];
         this.__z_e_listeners[evt] = handlers;
     }
     var item = {
         handler: handler,
         context: context
     };
     handlers.push(item);
     return item;
 };
 EventEmitter.prototype.off = function (evt, handler, context) {
     var handlers = this.__z_e_listeners[evt];
     if (handlers !== undefined) {
         var size = handlers.length;
         for (var i = 0; i < size; i++) {
             var item = handlers[i];
             if (item.handler === handler && item.context === context) {
                 handlers.splice(i, 1);
                 return;
             }
         }
     }
 };
 EventEmitter.prototype.emit = function (type, event) {
     var hanlders = this.__z_e_listeners[type];
     if (hanlders !== undefined) {
         var size = hanlders.length;
         for (var i = 0; i < size; i++) {
             var ef = hanlders[i];
             var handler = ef.handler;
             var context = ef.context;
             handler.apply(context, [event]);
         }
     }
 };
复制代码

测试代码:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>EventEmitter Test</title>
    <script src="./EventEmitter.js"></script>
    <script>
        var zObj = function () {
            this._props = {};
            this._emitter = new EventEmitter();
        };
        zObj.prototype.set = function (key, value) {
            var old = this._props[key];
            if (old !== value) {
                this._props[key] = value;
                this.emitChange(key, value, old);
            }
        };
        zObj.prototype.get = function (key) {
            return this._props[key];
        };

        zObj.prototype.onChange = function (handler, context) {
            this._emitter.on("change", handler, context);
        };
        zObj.prototype.offChange = function (handler, context) {
            this._emitter.off("change", handler, context);
        };
        zObj.prototype.emitChange = function (p, nv, ov) {
            this._emitter.emit("change", {
                source: this,
                property: p,
                newValue: nv,
                oldValue: ov
            });
        };

        var obj = new zObj();
        obj.onChange(function (evt) {
            console.log(evt)
        });
        obj.set("id", 1);
        obj.set("id", 2);
    </script>
</head>
<body>
</body>
</html>
            
复制代码

函数

主要有以下三个功能函数:

  • on :添加事件监听器
  • off:移除事件监听器
  • emit:派发事件
posted @ 2019-07-10 16:49  boonya  阅读(212)  评论(0编辑  收藏  举报
我有佳人隔窗而居,今有伊人明月之畔。
轻歌柔情冰壶之浣,涓涓清流梦入云端。
美人如娇温雅悠婉,目遇赏阅适而自欣。
百草层叠疏而有致,此情此思怀彼佳人。
念所思之唯心叩之,踽踽彳亍寤寐思之。
行云如风逝而复归,佳人一去莫知可回?
深闺冷瘦独自徘徊,处处明灯影还如只。
推窗见月疑是归人,阑珊灯火托手思忖。
庐居闲客而好品茗,斟茶徐徐漫漫生烟。

我有佳人在水之畔,瓮载渔舟浣纱归还。
明月相照月色还低,浅近芦苇深深如钿。
庐山秋月如美人衣,画堂春阁香气靡靡。
秋意幽笃残粉摇曳,轻轻如诉画中蝴蝶。
泾水潺潺取尔浇园,暮色黄昏如沐佳人。
青丝撩弄长裙翩翩,彩蝶飞舞执子手腕。
香带丝缕缓缓在肩,柔美体肤寸寸爱怜。
如水之殇美玉成欢,我有佳人清新如兰。
伊人在水我在一边,远远相望不可亵玩。