网上到处都是订阅者和观察者的代码实现,现在不知道什么场景,或者更简单实际的例子说明一下问题?
比如 Vue
、React
等等框架中
视图层的输入能影响到模型层,反之亦然,即双向绑定
这里的 怎么影响,就是靠订阅者观察者,因为 js
没有 Java
之类语言有的反射能力,只能靠这个去做一些数据绑定的事情。
一般的用在2个业务相互独立的模块或流程中。
比如说 有个视频播放器控件 提供了播放/停止的回调 叫onPlay 每当视频开始播放或者暂停的时候就会调用该方法
// status: 播放状态 1play 0pause
function onPlay(status){}
正常情况下我们要在回调里做什么处理只能先新建一个播放器,然后注册回调来执行相关逻辑
var player = new Player()
player.onPlay = function(status){
console.log(status === 1 ? '播放' : '暂停')
}
但是如果说有个场景,是处于你这个模块的外层,感知不到player这个变量,不知道这个视频有没有注册。
比如说在页面右上角有一个小图标 自动切换播放/停止的状态 那怎么办?这个时候你用了观察者模式,只需要注册订阅该事件就完了,然后比如说其他还有什么地方需要知道视频的播放状态的,也是订阅一下就好了
正因为这样的模式,会导致代码的可读性变差,因为逻辑不是写在一个地方的,所以在使用的时候需要权衡利弊
简单来说 大部分 主流框架 都 这个影子, jquery 里的 promise实现 和 事件系统 貌似 也是 这种。
redux 、 vuex 状态管理也是这种, 好多好多 都有。
我感觉这种实现, 也是为程序 解耦提供 方便, 我感觉。
自己写的 简单订阅
export const Event = function () {
// 类型
this.typeList = {}
}
Event.prototype.on = function ({type, fn}){
if (this.typeList.hasOwnProperty(type)) {
this.typeList[type].push(fn)
} else {
this.typeList[type] = []
this.typeList[type].push(fn)
}
}
Event.prototype.off = function({type, fn}) {
if (this.typeList.hasOwnProperty(type)) {
let list = this.typeList[type]
let index = list.indexOf(fn)
if (index !== -1 ) {
list.splice(index, 1)
}
} else {
console.warn('not has this type')
}
}
Event.prototype.once = function ({type, fn}) {
const fixFn = (value) => {
fn.call(this, value)
this.off({type, fn: fixFn})
}
this.on({type, fn: fixFn})
}
Event.prototype.trigger = function (type, value, context){
context = context ? context : null
if (this.typeList.hasOwnProperty(type)) {
this.typeList[type].forEach(fn => {
fn.call(context, value)
})
}
}
10 回答11.2k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答1.4k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
真实的例子——网站登录
假如我们正在开发一个商城网站,网站里有 header 头部、nav 导航、消息列表、购物车等模块。
如果它们和用户信息模块产生了强耦合,比如下面这样 的形式:
等到有一天,项目中又新增了一个收货地址管理的模块,这个模块本来是另一个同事所写的,在最后部分加上这行代码:
我们就会越来越疲于应付这些突如其来的业务要求,要么跳槽了事,要么必须来重构这些代码。
摘自个人博客:订阅者实际应用