- 作者:老汪软件技巧
- 发表时间:2024-11-29 04:02
- 浏览量:
之前写过一个比较常见的事件通知功能(订阅、发布 EventBus),使用上中规中矩,甚至还写了一个自动销毁的事件订阅功能,参考这里
现在又有一个特殊场景,就是需要在订阅前支持发布,订阅的同时可以响应已经发布过的内容,也就是需要额外支持预发布功能,这种场景虽然很少见但是偶然也是可以见到,某个需求需要跳转到某个页面并执行发布内容,页面不存在时初始化并执行发布内容,页面存在时,直接发布内容
那我们就随手写一个特殊的 eventbus 把,让预发布的内容也能够得到响应,即使没订阅,在订阅的时候也能立刻得到响应,并且正常订阅的也能得到响应,并且也顺道实现自动销毁效果吧
ps:这个功能是小程序遇到的类似功能,当然有更加粗暴的解决方法,但是个人感觉直接写一个类似的能够使用的功能也是不错,也花不了多久时间,还能
ps2:简单粗暴方法也很简单,保存一个单例或者对象,跳转前,更新要处理的内容,另外一个页面有一个 onShow 的方法,也就是每次进入页面都会调用的方法,直接在里面查询是否相同,响应事件即可,当然也可以更细致
接下来介绍一下摘要步骤:
首先梳理一个普通的支持订阅、发布的事件功能类进一步完善该事件功能,hook 销毁函数,并完成自动销毁功能(这里只支持小程序的page页了)支持发布的时候预订阅(也就是完成一个没有回调的订阅),保存参数,以便于实际订阅的时候能够察觉到,并响应订阅的时候查找是否有预订阅功能(也就是完成一个没有回调的订阅),发现已经存在预订阅就完善订阅并相应一次,此后变成正常订阅发布功能,参考步骤1
//特殊的 emit,未注册事件时也可以通知,当注册时响应一次,未通知则不响应
var events = [] //{ name, func, context, args}
//wx page 组件使用,目前一个name仅支持一个func
function $on(eventName, func, context) {
if (!context) {
throw new Error('请传递当前会话context,page->this')
}
const event = events.find(e => e.name === eventName)
if (event) {
if (!event.func || !event.context) {
event.func = func
setupContext(event, context)
event.func(...event.args)
} else {
event.func = func
}
} else {
subscribe(eventName, func, context, [])
}
}
//强制相应,注册后会立即响应emit的事件,没有会注册事件等注册完毕后有事件立即响应一次
function $emit(eventName, ...args) {
const event = events.find(e => e.name === eventName)
if (event) {
event.func(...args)
} else {
subscribe(eventName, null, null, args)
}
}
//正常订阅
function subscribe(eventName, func, context, args) {
const event = {}
event.name = eventName
event.func = func
if (context) {
setupContext(event, context)
} else {
event.args = args
}
events.push(event)
}
//设置context
function setupContext(event, context) {
event.context = context
event.onUnload = context.onUnload
context.onUnload = () => {
events = events.filter(e => e.context !== context)
event.onUnload()
console.log('onUnload')
}
}
module.exports = {
$on: $on,
$emit: $emit
}
上面的实际上还不够完善,少了一些功能,也多了一些功能,可以自行改动,实际上东西是死的人是活的,只要有想法,想法符合实际,那么就一定能完成,多编写一些小工具,能够减少我们的脑细胞老化