JS设计模式-观察者模式

JS设计模式-观察者模式

我个人觉得观察者模式(订阅-发布模式)是最常会见到的一种设计模式了,即是没了解过设计模式,你应该也见过:

window.addEventListener('click', function() {
  // TODO
})

又或者是在VUE开发中父子组件使用$emit$on进行事件通信,以及不相关组件的eventbus通信。这都是比较常见的观察者模式。

让我们来试想这样一种情况:

function fnA() {
    console.log('function A');
}
function fnB() {
    fnA()
    console.log('function B');
}
function fnC() {
    fnB()
    console.log('function C');
}

C调用了B,B又调用了A,如此强的依赖性会导致这其中有一个地方出了问题,都会导致后续的函数异常报错。

还有一种情况就是上面提到的跨文件、跨组件的事件传递,为此我们来简单设计一个观察者,我写的是极简版的,缺少很多判断及验证,如果你想看更详细的,建议来参考VUE的源码,大概在==54==行开始。

首先创建一个观察者对象,在开发中一般是放在全局的js文件中的。

const event = {
    // 存放发布的事件
    eventList: {},
    // 发布,为了方便理解,这里我默认同一个key下只能有一个事件
    $emit: function (key, fn) {
        Reflect.set(this.eventList, key, fn)
    },
    // 订阅,有key就执行,否则返回false
    $on: function (key, ...arguments) {
        return Reflect.has(this.eventList, key) ? this.eventList[key](...arguments) : false
    }
}

上面的例子稍微优化一下:

function fnA() {
    console.log('function A');
}

event.$emit('fnB', function() {
    fnA()
    console.log('function B');
})

function fnC() {
    event.$on('fnB')
    console.log('function C');
}

乍一看似乎没什么变化,但是却降低了三个函数之间的耦合,在fnC中,它只需要订阅执行时间就可以了,无论是fnA被删除了,还是fnB中出现异常报错了,都不会影响fnC的执行了。

甚至可以里用观察者对象来进行跨文件、组件的事件传递

在A文件中发布:

// 发布
 event.$emit('test', function (name, sex) {
   console.log(`${name}: ${sex}`);
})

可以在B文件中订阅事件:

// 订阅
event.$on('test', '张三', '男')	// 张三:男

可以发现,这种设计模式的最大好处就解耦合和跨文件的事件传递,但是它也有个问题,就是把函数之间的关系隐藏的更深了,维护起来追踪BUG可能会变得复杂。

各位可以再完善一下订阅对象,例如window.addEventListener添加十个同名事件,在订阅的时候会十个事件全部执行,另外还有window.removeEventListener来取消订阅。甚至还可以添加命名空间来让订阅对象各取所需。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cRack_cLick

感谢你的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值