1. 程式人生 > >Js實現訂閱釋出模式(讓你的程式碼寫得賊六)

Js實現訂閱釋出模式(讓你的程式碼寫得賊六)

簡單例子

 var salesoffice = {}; //定義售樓處

     salesoffice.clientList = []; //快取列表,存放訂閱者的回撥函式

    salesoffice.listen = function (key,fn) { //增加訂閱者
        if(!this.clientList[key]){
            this.clientList[key] = [];
        }
        this.clientList[key].push(fn); //訂閱的訊息新增進快取列表
    };

    salesoffice.trigger = function
() {
//釋出訊息 var key = Array.prototype.shift.call(arguments); //取出訊息型別 fns = this.clientList[key]; if(!fns || fns.length ===0 ){ //如果沒有訂閱改訊息,則返回 return false; } for (var i = 0,fn;fn=fns[i++];){ fn.apply(this,arguments); //arguments 是釋出訊息時帶上的引數
} }; //測試例子 salesoffice.listen('squareMeter88',function (price) { //小明訂閱訊息 console.log("價格=" + price ); }); salesoffice.listen('squareMeter110',function (price) { //小紅訂閱訊息 console.log("價格=" + price ); }); salesoffice.trigger('squareMeter88',2000000); salesoffice.trigger('squareMeter110'
,3000000);

通用實現


    //通用實現

    var event = {
        clientList:[],
        listen : function (key,fn) {
            if(!this.clientList[ key ]){
                this.clientList[ key ] = [];
            }
            this.clientList[key].push(fn);
        },
        trigger:function () {
            var key = Array.prototype.shift.call(arguments),

                fns = this.clientList[ key ];

            if(!fns || fns.length===0){
                return false;
            }

            for (var i=0,fn;fn = fns[i++];){
                fn.apply(this,arguments);
            }
        }
    };

    //在定義一個instalEvent 函式,這個函式可以給所有的物件都動態安裝釋出訂閱模式

    var installEvent = function (obj) {
        for (var i in event){
            obj[i] = event[i];
        }
    }

    var salesOffices = {};

    installEvent(salesOffices);

    salesOffices.listen('squareMeter88',function (price) {   //小明訂閱訊息
            console.log("價格=" + price );
        });


    salesOffices.listen('squareMeter110',function (price) {   //小紅訂閱訊息
            console.log("價格=" + price );
        });

    salesOffices.trigger('squareMeter88',2000000);
    salesOffices.trigger('squareMeter110',3000000);


    //取消訂閱事件

    event.remove = function (key,fn) {
        var fns = this.clientList[ key ];

        if( !fns ){ //如果key對應的訊息沒有被人訂閱,則直接返回
            return false;
        }
        if( !fn ){ //如果傳入的具體的回撥函式,表示需要取消key對應訊息的所有訂閱
            fns && (fns.length=0);
        }else{
            for (var l = fns.length - 1;l >=0;l--){
                var _fn = fns[l];
                if(_fn === fn){
                    fns.splice(l,1); //刪除訂閱者的回撥函式
                }
            }
        }
    }

    var salesOffices = {};

    installEvent(salesOffices);

    salesOffices.listen('squareMeter88',fn1 = function (price) {   //小明訂閱訊息
        console.log("價格=" + price );
    });


    salesOffices.listen('squareMeter110',fn2 = function (price) {   //小紅訂閱訊息
        console.log("價格=" + price );
    });

    salesOffices.remove('squareMeter88',fn1); //刪除小明的訂閱
    salesOffices.trigger('squareMeter110',2000000);

全域性的釋出–訂閱物件

        //全域性的釋出--訂閱物件

    var Event = (function () {

        var clientList = {},
            listen,
            trigger,
            remove;

        listen = function (key,fn) {
            if(!clientList[key]){
                clientList[key]=[];
            }
            clientList[key].push(fn);
        };

        trigger = function () {
            var key = Array.prototype.shift.call(arguments),
                fns = clientList[key];
            if(!fns || fns.length===0){
                return false;
            }

            for (var i =0,fn;fn=fns[i++];){
                fn.apply(this,arguments);
            }

        };

        remove = function (key,fn) {
            var fns = clientList[key];
            if(!fns){
                return false
            }

            if(!fn){
                fns && (fns.length=0);
            }else{
                for (var l=fns.length-1;l>=0;l--){
                    var _fn = fns[l];
                    if(_fn===fn){
                        fns.splice(l,1);
                    }
                }
            }
        };
        return {
            listen:listen,
            trigger:trigger,
            remove:remove,
        }
    })();

    Event.listen('squareMeter88',function (price) {
        console.log("價額="+price);
    });

    Event.trigger('squareMeter88',2000000);

最後想說:

最近才想著把自己這三年來學到的東西分享出來,技術是無邊界的,共享才是趨勢!下面是我的個人公眾號,喜歡的朋友可以關注一下哈。

二維碼