摘要:在触发的时候,回调此方法,从而触发函数。发布订阅模式比较适合写封装插件,我认为拿来写业务逻辑代码,有点不太好用。接下来,我准备用这个模式封装一个上传的组件。
初始化Event对象
var initEvent = function(obj) { for(var i in event) { obj[i] = event[i]; } };
主代码:
var event = { list: [], listen: function(key, fn) { // 确定监听的事件容器默认是一个空数组 if(!this.list[key]) { this.list[key] = []; } // 订阅的消息添加到缓存列表中 this.list[key].push(fn); // 链式调用 return this }, trigger: function(){ // 获取trigger 函数参数的第一个参数,即key键 // 此时arguments 是trigger的参数类数组 var key = Array.prototype.shift.call(arguments); // 拿到对应key的监听事件数组 var fns = this.list[key]; // 如果没有订阅过该消息的话,则返回 if(!fns || fns.length === 0) { return; } for(var i = 0, fn;i < fns.length; i ++) { fn = fns[i] //逐个调用key键所对应监听事件数组函数 // 此时arguments 同样也是trigger的参数类数组,只不过少了第一个参数 // 将此参数传递给fn函数作为形参 // this 也是fn的执行作用域 fn.apply(this, arguments); } } };
调用执行:
// 新建一个比如小红的对象 var shoeObj = {}; // 初始化小红对象 initEvent(shoeObj); // 小红同时订阅如下消息(链式调用) shoeObj.listen("red",function(size, price){ console.log("尺码是:"+size); console.log("price是" +price) }).listen("block", function (size, price) { console.log("尺码是:"+size); console.log("price是" +price) }) shoeObj.trigger("red", 40, 500); shoeObj.trigger("block",42, 300);
订阅了消息后,我们可能会remove掉消息,所以Event对象新增一个方法:
// 略 remove : function(key, fn) { var fns = this.list[key] // 如果key对应的消息没有订阅过的话,则返回 if(!fns) return // 如果没有传入具体的回调函数,表示需要取消key对应消息的所有订阅 if(!fn) { fns.length = 0 // 或者this.list[key] = [] // fns = [] //fns = [] 这样写后,实际this.list[key]中的回调数组 //依然存在,因为初始fns指向this.list[key]这个数组(数组是一个引用类型) //fns = [],代表我们将fns又指向了一个新的数组长度为空的引用数组,而这个 // 新的引用数组 和this.list[key]这个引用数组是计算机里面占用两个不同的 // 堆栈。 }else { for(var i = 0; i < fns.length; i ++) { var _fn = fns[i] if(_fn === fn) { fns.splice(i, 1) // 删除订阅者的回调函数 } } } }, // 略
调用
// 小红订阅如下消息 同时在red上面订阅了两个消息 // 注意fn1 和fn2 这种写法,比较少见,实际fn1,fn2成为了一个全局变量 // 在remove的时候,作为具体的参数传递 shoeObj.listen("red",fn1 = function(size, price){ console.log("尺码是1----" +size); console.log("price是1----" +price) }).listen("red", fn2 = function(size, price){ console.log("尺码是2----" +size); console.log("price是2----" +price) }) //remove 掉fn2 shoeObj.remove("red", fn2) // 触发回调 此时只会回调fn1 shoeObj.trigger("red", 40, 500); //如果remove 不传参数,就会将red中所有的监听全部remove掉 shoeObj.remove("red") shoeObj.trigger("red", 40, 500);
结束语
发布订阅模式是js中36中设计模式中最常见的模式,也是很重要的设计模式。其实我们在写项目逻辑代码的时候,无形中也运用了这个思想,最常见的是click触发回调。比如我们定义一个方法,在定义的时候已经listen在一个对象上,或window对象上。在click触发的时候,回调此方法,从而触发函数。
发布订阅模式比较适合写封装插件,我认为拿来写业务逻辑代码,有点不太好用。当然这只是我自己的观点。
接下来,我准备用这个模式封装一个上传的组件。
附录(参考文献)
cn一篇博文
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/107046.html
摘要:今天说说观察者模式,这是一个非常常见的模式,很多事件的分发都基于此模式。这里将从一个题目来说说此模式的使用,有这样一道题某市一家报社开张,市民订阅报纸,尝试使用观察者模式解决此问题。在使用观察者模式前,先说说普通的处理方法。 今天说说观察者模式,这是一个非常常见的模式,很多事件的分发都基于此模式。 这里将从一个题目来说说此模式的使用,有这样一道题: 某市一家报社开张,市民订阅报纸,尝试...
摘要:以下方式写提示未定义涉及闭包作用域链的问题改进方式调用实例化回调函数执行成功,并执行函数,此时在回调队列里面添加一一个函数,并将的参数传递出去。否则直接执行回调函数,不会由来触发的回调函数执行。 function Promise(fn){ //需要一个成功时的回调 var self = this var callback; //一个实例的方法,用来注册异...
摘要:接下来我们看下三类异步编程的实现。事件监听事件发布订阅事件监听是一种非常常见的异步编程模式,它是一种典型的逻辑分离方式,对代码解耦很有用处。 一、 一道面试题 前段时间面试,考察比较多的是js异步编程方面的相关知识点,如今,正好轮到自己分享技术,所以想把js异步编程学习下,做个总结。下面这个demo 概括了大多数面试过程中遇到的问题: for(var i = 0; i < 3; i++...
摘要:想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。创建型设计模式主要有简单工厂模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式和单例模式,下面一一道来。而工厂方法模式本意是将实际创建对象的工作推迟到子类中。 接触前端两三个月的时候,那时候只是听说设计模式很重要,然后我就去读了一本设计模式的书,读了一部分,也不知道这些设计模式到底设计出来干嘛的,然后就没再看了。后...
摘要:或许以前认为订阅发布模式是观察者模式的一种别称,但是发展至今,概念已经有了不少区别。参考文章订阅发布模式和观察者模式真的不一样 首选我们需要先了解两者的定义和实现的方式,才能更好的区分两者的不同点。 或许以前认为订阅发布模式是观察者模式的一种别称,但是发展至今,概念已经有了不少区别。 订阅发布模式 在软件架构中,发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特...
阅读 3117·2023-04-26 02:33
阅读 3085·2023-04-25 21:33
阅读 892·2021-09-02 09:56
阅读 2885·2019-08-30 15:44
阅读 2439·2019-08-30 13:15
阅读 1015·2019-08-30 13:04
阅读 1616·2019-08-29 15:09
阅读 3936·2019-08-26 18:26