JS模式---发布、订阅模式

  • 发布订阅模式又叫观察者模式,它定义一种一对多的依赖关系,
  • 当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
document.body.addEventListener('click', function () {
            alert(1);
        }, false);
        document.body.addEventListener('click', function () {
            alert(2);
        }, false);
        document.body.addEventListener('click', function () {
            alert(3);
        }, false);
        document.body.click();

发布--订阅模式的通用实现

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);
                }
            },
            remove: function (key,fn) {
                var fns = this.clientList[key];
                if (!fns) {
                    return false;
                }
                if (!fn) {
                    fns && (fns.length = 0);
                } else {
                    for (var i = fns.length-1; i >= 0; i--) {
                        var _fn = fns[i];
                        if (_fn === fn) {
                            
                            fns.splice(i, 1);
                            console.log("删除成功!");
                        }
                    }
                }
            }
        };
        //给所有对象设置发布-订阅功能
        var installEvent = function (obj) {
            for (var i in event) {
                obj[i] = event[i];
            }
        };

        var salesOffices = {};
        installEvent(salesOffices);
        //订阅
        salesOffices.listen("89cm3",f1= function (price) {
            console.log("价格:"+price);
        });
        salesOffices.listen("120cm3",f2= function (price) {
            console.log("价格:" + price);
        });
        //发布
        salesOffices.trigger("89cm3", 1200000);
        salesOffices.trigger("120cm3", 2200000);

        salesOffices.remove("89cm3", f1);
        salesOffices.trigger("89cm3", 1200000);

  • 防止全局命名冲突再重构。
var Event = (function () {
            var global = this,
                Event,
                _default = 'default';

            Event = function () {
                var _listen,
                    _trigger,
                    _remove,
                    _slice = Array.prototype.slice,
                    _shift = Array.prototype.shift,
                    _unshift = Array.prototype.unshift,
                    namespaceCache = {},
                    _create,
                    find,
                    each = function (ary, fn) {
                        var ret;
                        for (var i = 0; i < ary.length; i++) {
                            var n = ary[i];
                            ret = fn.call(n, i, n);
                        }
                        return ret;
                    };

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

                _remove = function (key,cache,fn) {
                    if (cache[key]) {
                        if (fn) {
                            for (var i = cache[key].length; i >= 0; i--) {
                                if (cache[key][i] === fn) {
                                    cache[key].splice(i, 1);
                                }
                            }
                        } else {
                            cache[key] = [];
                        }
                    }
                };

                _trigger = function () {
                    var cache = _shift.call(arguments),
                        key = _shift.call(arguments),
                        args = arguments,
                        _self = this,
                        ret,
                        stack = cache[key];

                    if (!stack || !stack.length) {
                        return;
                    }
                    return each(stack, function () {
                        return this.apply(_self, args);
                    });

                };

                _create = function (namespace) {
                    var namespace = namespace || _default;
                    var cache = {},
                        offlineStack = [],
                        ret = {
                            listen: function (key, fn, last) {
                                _listen(key, fn, cache);
                                if (offlineStack === null) {
                                    return;
                                }
                                if (last === 'last') {
                                    offlineStack.length && offlineStack.pop()();
                                } else {
                                    each(offlineStack, function () {
                                        this();
                                    });
                                }
                                offlineStack = null;
                            },
                            one: function (key, fn, last) {
                                _remove(key, cache);
                                this.listen(key, fn, last);
                            },
                            remove: function (key, fn) {
                                _remove(key, cache, fn)
                            },
                            trigger: function () {
                                var fn,
                                    args,
                                    _self = this;
                                _unshift.call(arguments, cache);
                                args = arguments;
                                fn = function () {
                                    return _trigger.apply(_self, args);
                                };
                                if (offlineStack) {
                                    return offlineStack.push(fn);
                                }
                                return fn();
                            }
                        };
                    return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;
                };

                return {
                    create: _create,
                    one: function (key, fn, last) {
                        var event = this.create();
                        event.one(key,fn,last);
                    },
                    remove: function (key,fn) {
                        var event = this.create();
                        event.remove(key,fn);
                    },
                    listen: function (key,fn,last) {
                        var event = this.create();
                        event.listen(key,fn,last);
                    },
                    trigger: function () {
                        var event = this.create();
                        event.trigger.apply(this,arguments);
                    }
                };

            }();
            return Event;
        })();
原文地址:https://www.cnblogs.com/meiyh/p/6485174.html