• 观察者模式创建自定义事件


    简述观察者模式

      观察者模式又称发布-订阅模式,主要做“订阅”、“发布”、“撤销订阅”三种操作,事件处理系统就是这种模式的一个实现。

      被观察者定义一个缓存,保存订阅者的处理函数。当有新的消息发布,被观察会去检索缓存看有没有观察者订阅这个消息,有的话调用对应的处理函数。

      观察者模式使得观察者和被观察者相互分离,避免了相互调用的紧耦合状态。从效果上看,实现相同的目的,观察者模式可以避免过多的条件分支,同时订阅发布的频率难以影响代码的复杂度。

    观察者模式在JS中的实现

      首先定义一个观察者模式对象(Observer),观察者有“发布”、“订阅”、“撤销”三种操作以及一个保存订阅处理函数的缓存。缓存保存类型与回调函数的最终结构如下:

    {
      type1 : [callback1, callback2,...],
      type2 : [callback3],
      ...  
    }

      整个对象定义如下:

    var Observer = {
       _cachePool : {},
       fire : function(type, msg){},//发布函数,传递发布类型以及相应消息
       on : function(type, callback){},//订阅函数,传递订阅类型与处理函数
       un : function(type, callback){}//解订函数,传递要取消某类型及某处理函数    
    };

      再看发布函数。发布函数做的事是找到缓存池里对应类型的所有处理函数,然后依次执行一遍这些处理函数。

    Observer.fire = function(type, msg) {
        var fns = this._cachePool[type],
            len = fns.length;
        for(var i = 0, fn; i < len; i++) {
            fn = fns[i];
            fn.call(this, msg);
        }
    };

      接着看订阅函数。订阅函数做的事是把订阅的类型与回调函数保存进_cachePool中。先判断缓存中有该类型的空间没,没有的话创建该类型空间再保存回调函数,有的话直接保存。

    Observer.on = function(type, callback) {
        if(!this._cachePool[type]) {
            this._cachePool[type] = [];
        }
        this._cachePool[type].push(callback);
    };

      最后看解除订阅。它做的事是把缓存池中相应类型的回调函数删除。

    Observer.un = function(type, callback) {
        var fns = this._cachePool[type];
        if(fns) {
            this._cachePool[type] = fns.filter(function(item){
                return item !== callback;
            });
        }
    };

      解订函数删除相应回调函数用到Array.prototype.filter函数,这个函数属于Ecma 5新增内容。古董浏览器没有这个函数,我们可以自己写一个兼容的filter:

    var filter = function(arr, callback) {
        var resultArr = [];
        for(var i = 0, len = arr.length; i < len; i++) {
            if(callback.call(arr[i], arr[i], i)) {
                resultArr.push(arr[i]);
            }
        }
        return resultArr;
    }

      当然,我们可以扩展Array:Array.prototype.filter = Array.prototype.filter || filter;这样就不用调整解订函数filter的用法了。

      观察者模式测试如下:

    Observer.on('click', onclick);
    Observer.on('click', function(msg) {console.log('click...拉姆达' + " " + msg)});
    Observer.on('click', onclick);
    Observer.fire('click', "hello world!");
    Observer.un('click', onclick);
    console.log("解订后:");
    Observer.fire('click', "hello world!");
    
    //结果:
    click..hello world!
    click...拉姆达 hello world!
    click..hello world!
    解订后:
    click...拉姆达 hello world!

      简易自定义事件达成!

      当然,你可以用原生事件处理你新定义的事件,只要实现订阅好事件,然后在原生事件里发布该事件的消息即可。后面的简易富文本编辑器(二)中会具体实践。

      

  • 相关阅读:
    软件工程评分表
    评论
    团队成员介绍
    第九天冲刺
    第八天冲刺
    第七天冲刺
    第六天冲刺
    第五天冲刺
    第四天冲刺
    第三天冲刺
  • 原文地址:https://www.cnblogs.com/longhx/p/5440178.html
Copyright © 2020-2023  润新知