码疯窝

Javascript 通过继承实现观察者模式

2015/09/11 15:12:35    分类: 技术随笔    1人评论 次浏览

最近在工作当中发现部分代码维护起来困难, 一个方法传入N个callback function, 可读性差, 维护起来麻烦.
原代码类似这种情况.

function Dialog() {
    this._text = 'I am a dialog';
}
Dialog.prototype.open = function (cbYes, cbNo) {
    if (confirm(this._text)) {
        if (typeof(cbYes) === 'function') {
            cbYes.call(this);
        }
    } else {
        if (typeof(cbNo) === 'function') {
            cbYes.call(this);
        }
    }
}
var dlg = new Dialog();
dlg.open(
    function () {alert('Clicked YES');},
    function () {alert('Clicked NO');}
);

于是, 我加入一个Event类来实现观察者模式, 让Dialog继承Event就行. Event代码如下:


(function () {
    function Event() {
        this.evtList = {};
        this.onceList = {};
    }
    Event.prototype.on = function (evt, func) {
        if (this.evtList[evt]) {
            this.evtList[evt].push(func);
        } else 
            this.evtList[evt] = [func];
        return this;
    };

    Event.prototype.once = function (evt, func) {
        if (this.onceList[evt]) {
            this.onceList[evt].push(func);
        } else
            this.onceList[evt] = [func];
        return this;
    };

    Event.prototype.trigger = function (evt) {
        var list = this.evtList[evt], i = 0, len = 0, tmp;
        if (list && list.length > 0) {
            list.forEach(function(item) {
                item.apply(this, Array.prototype.slice.call(arguments, 1));
            });
        }
        list = this.onceList[evt];
        if (list && list.length > 0) {
            len = list.length;
            while (tmp = list.pop()) {
                tmp.apply(this, Array.prototype.slice.call(arguments, 1));
            }
        }
        return this;
    };

    window.Event = Event;
})();

支持on/once 添加事件(on和once的区别在于once事件执行完就会被销毁), 然后用trigger去触发事件. 同时支持多个事件绑定, 事件响应的顺序为事件的绑定顺序.

于是, 原demo 代码就可以改为:

function Dialog() {
    this._text = 'I am a dialog';
}
Dialog.prototype = new Event(); // It's imporant here.

Dialog.prototype.open = function () {
    if (confirm(this._text)) {
        this.trigger('yes');
    } else {
        this.trigger('no');
    }
}
var dlg = new Dialog();

dlg.on('yes', function () {
    alert('yes trigger 1');
}).on('yes', function () {
    alert('yes trigger 2');
}).on('no', function () {
    alert('no trigger 1');
}).once('yes', function () {
    alert('this event only show once');
});

dlg.open();
dlg.open();
继续查看有关 技术随笔的文章

1个访客评论

  1. Sam Pang

    一血 沙发

    qweqwe Reply