【学习】发布订阅者模式在小程序的运用
【设计模式】 发布订阅者模式在小程序的运用
最近在学习设计模式,设计模式无关语言,也无关产品,是一种编码的思维方式,可以使我们更好的管理我们的代码,最大的好处莫过于 解耦,从业务代码中抽离出可复用高的代码,不同模块相互独立;
这篇文章开始记录一下 发布——订阅模式
介绍
[代码]Javascript设计模式与开发实践[代码] 一书对其解释如下:
发布—订阅模式又叫观察者模式,它定义对象间 的一种一对多的依赖关系,当一个对象的状态发 生改变时,所有依赖于它的对象都将得到通知。 在JavaScript开发中,我们一般用事件模型来替代 传统的发布—订阅模式
书中还有一个关于网站登录的例子的解释很精彩,生动的解释该模式下的模块分离以及该模式下的具体运用。
小程序端的运用
由于最近接触的小程序端的开发较多,因此,打算用一个小程序的场景来学习实践一下 发布——订阅模式
场景
A页面是一个列表页面,点击列表某项进入详情页面,在详情页面执行删除(修改)操作,后退返回A页面,需要刷新接口,从新获取数据;
实战
编写发布-订阅模式对象
[代码]// observer.js
const Event = (() => {
// 通知模块列表
let clientList = []
/**
* 监听
* @param {*} key 模块名称
* @param {*} fn 回调函数
*/
const listen = function(key, fn) {
// 判断是否存在为key值的模块,没有需要初始化空数组
if (!clientList[key]) {
clientList[key] = []
}
// 模块添加监听回调函数
clientList[key].push(fn)
}
/**
* 发布通知
*/
const trigger = function() {
const key = Array.prototype.shift.call(arguments)
const fns = clientList[key]
// 如果该模块下没有注册事件,直接返回
if (!fns || fns.length === 0) {
return false
}
// 执行模块注册的所有事件
fns.map(fn => fn && fn.apply(this, arguments))
}
/**
* 注销事件
* @param {*} key
* @param {*} fn
*/
const remove = function(key, fn) {
const fns = clientList[key]
// 模块没有注册事件
if (!fns) {
return false
}
// 没有传入需要注销的事件,全部清空
if (!fn) {
fns && (fns.length = 0) // 这里很精彩,直接数组清空即可
} else {
// 清掉该事件
const index = fns.findIndex(item => item === fn)
if (index !== -1) {
fns.splice(index, 1)
}
}
}
return {
listen,
trigger,
remove,
}
})();
module.exports = Event
[代码]
编写列表页面,注册列表删除事件
[代码]// observerPage.js
const Event = require('../../designPatterns/observer');
Page({
data: {
list: [
{id: 1, value: '第1项'},
{id: 2, value: '第2项'},
{id: 3, value: '第3项'},
{id: 4, value: '第4项'},
{id: 5, value: '第5项'},
{id: 6, value: '第6项'},
{id: 7, value: '第7项'},
{id: 8, value: '第8项'},
{id: 9, value: '第9项'},
{id: 10, value: '第10项'},
]
},
onLoad() {
// 注册通知
Event.listen('observerList', this.delete)
},
delete(id) {
const newList = this.data.list.filter(item => item.id !== +id)
this.setData({ list: newList })
},
toOperatePage(e) {
const { item } = e.currentTarget.dataset
wx.navigateTo({
url: `./operate?id=${item.id}`
})
}
})
[代码]
编写操作页面,发布删除操作
[代码]const Event = require('../../designPatterns/observer');
Page({
data: {
id: 1,
},
onLoad(options) {
this.setData({id: options.id})
},
handleDel() {
wx.showToast({
title: '删除成功'
})
Event.trigger('observerList', this.data.id)
}
})
[代码]
小结
创建订阅者本身要消耗一定的时间和内存,而且当你订阅一个消息后,也许此消息最后都未发生,但这个订阅者会始终存在于内存中(也就是[代码]clientList对象中[代码]);过度使用必然会造成堆栈溢出,而且模块之间的关联会隐藏其中,难以排查bug。
项目调试地址
项目调试地址: https://github.com/csonchen/mina-app
感谢
Javascript设计模式与开发实践 —— 曾探