前端开发:深入了解Vue数据响应式原理
|
admin
2024年4月26日 12:6
本文热度 530
|
Vue的响应式原理是基于发布订阅模式实现的。所以先来了解一下发布订阅模式【Publish-Subscribe Pattern】
了解前端常见的两种设计模式
发布-订阅模式 Publish-Subscribe Pattern
由发布者Publisher
、订阅者列表Subscriber
、消息队列/调度中心Event Channel
组成的形式。发布者Publisher
和订阅者Subscriber
之间是互不相识,不直接通信交流的,而是通过消息队列进行。
可以理解为:某博主(发布者)发布了一个短视频在短视频平台(消息队列)上,每天上班搬砖的打工人(订阅者)趁着吃饭的时间,刷刷短视频,发现该博主的视频非常优秀有内容,于是在该短视频平台上订阅关注了该视频博主。然后该博主只要更新了视频,你就能接收到通知。
特点
- 松解耦:发布者订阅者通过中介进行通信,互不知晓对方存在。降低了组件间的耦合度,使得更容易理解维护和扩展。
- 扩展性:由于解耦性,可以更容易扩展。新增发布者或订阅者不影响现有组件。
- 灵活性:允许任何数量的发布者订阅者存在,支持多对多通信。删除、修改、新增不影响系统运行。
- 异步通信:支持异步通信,能更高效处理消息,提高响应性。
举例子
class eventChannel {
constructor() {
this.msgMap = {}
}
publish(name, param) {
const msg = this.msgMap[name]
if (msg) {
msg.subscribeList.forEach(subscribe => {
subscribe.callback(param)
})
}
}
subscribe(name, callback) {
const msg = this.msgMap[name]
if (msg) {
msg.subscribe.push({callback})
} else {
this.msgMap[name] = {
name,
subscribeList: [{callback}]
}
}
}
}
观察者模式 Observer Pattern
面试有时候会被问到观察者模式和发布-订阅模式之间有什么不同。简单的说:观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件,没有中介代替传递消息。
观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。
特点
- 可扩展性:可以随时添加新的观察者,或删除现有观察者。
举例子
let observerIds = 0
// 被观察者
class Subject {
constructor() {
this.observeres = []
}
addObservere(observer) {
this.observeres.push(observer)
}
removeObservere(obs) {
this.observeres = this.observeres.filter(observer => observer !== obs )
}
notify(data) {
this.observeres.forEach(observer => observer(data))
}
}
// 观察者
class Observer {
constructor() {
this.id = observerIds++
}
update(ob) {
// ...
}
}
Vue2 数据响应式原理
Vue2的数据对象是通过Object.defineProperty
进行数据劫持, 将其对象属性转化为响应式属性。同时,为每个属性创建一个Dep
对象,收集当前属性的依赖关系。这里的Dep
就相当于上文发布订阅模式中讲到的调度中心。
当读取数据时会触发getter,修改数据时会触发setter。Watcher对象作用是建立依赖关系,检测数据变化,并在数据变化时执行相应的更新操作。Watcher机制是基于异步更新的,这样能避免频繁更新,提高性能和优化用户体验。
Vue3 数据响应式原理
Vue3 是基于proxy的Observer,通过Proxy
拦截对象属性变化,通过Reflect
对原对象属性进行操作。
Proxy
:在目标对象之前假设一层拦截,可以对外界的访问进行改写。可以通过其get捕获器
拦截读取对象属性,通过set捕获器
拦截对象属性赋值。
Reflect
:提供了一组和Objct类似的方法,用于操作对象。Vue3中主要配合Proxy进行操作,以获取/设置代理对象属性值。
Vue3使用Proxy
替代Obejct.defineProperty
,解决了以下问题:
- 优化数组监听:
Proxy
可以直接拦截数组索引设置和长度变更。 - 嵌套对象处理:Vue2需要递归对每个子对象进行数据拦截,而
Proxy
代理整个对象,无论层级多深都能有效追踪数据变化。 - 全面属性监听:Vue2只能监听已注册的属性,Vue3能对对象属性的新增删除修改做全面监听和数据变化追踪。
该文章在 2024/4/28 21:13:50 编辑过