深入vue的响应式原理

本文深入解析Vue.js响应式系统的实现机制,包括Observer、Dep、Watcher三个核心类的作用,以及它们如何协同工作,实现数据变化与视图更新的联动。同时探讨了Vue的数据劫持策略、依赖收集过程和异步更新机制。
摘要由CSDN通过智能技术生成

在了解Vue的响应式原理之前,建议先去了解一下观察者模式

Vue实现响应式主要依赖于三个类:Observer、Dep、Watcher

对于data、props选项而言,Vue会通过Observer类的observe方法(instance/state.js的170行左右)将它们重新构建,具体来说,就是使用ES5里面的Object.defineProperty(...)方法将其变更为getter/setter形式,以便于对data、props选项内的数据进行劫持/监听。

在通过getter劫持数据的过程中,Vue为每一个data、props选项内的属性单独创建了Dep类实例(observer/index.js的170行左右),Dep类实例是一个调度中心,它会收集订阅了该属性的Watcher实例,存放在内部队列之中。

在通过setter监听数据的过程中,Vue会通过Dep类的notify方法发布消息(observer/index.js的224行左右),调用内部队列中的所有的Watcher类实例的update方法(observer/dep.js的44行左右),进而去重新渲染组件。

每一个Vue组件都会拥有一个对应的Watcher类实例,我们通常称这个类实例为观察者对象,它收集Vue的render函数渲染组件时所需要的依赖(其实就是在模板内使用了的props、state的数据),并且提供依赖变更时,Vue组件重新渲染所需要的函数。

Watcher类实例创建于createdbeforeMounted阶段(instance/lifecycle.js的206行左右),每当在模板内发现了一个第一次出现的依赖,Watcher实例都会被推入该依赖对应的Dep实例的内部队列之中。

以上是Vue实现双向数据绑定的代码实现,以下是其设计思想,可能读起来会有一些别扭。

下图十分明确的阐释了Vue双向绑定数据的整个流程:
首先通过一次渲染操作触发Data的getter(这里保证只有视图中需要被用到的data才会触发getter)进行依赖收集,这时候其实Watcher与data可以看成一种被绑定的状态(实际上是data的闭包中有一个Deps订阅者,在修改的时候会通知所有的Watcher观察者),在data发生变化的时候会触发它的setter,setter通知Watcher,Watcher进行回调通知组件重新渲染的函数,之后根据diff算法来决定是否发生视图的更新。

在Vue中,是不允许动态的为Vue实例添加数据property的,即是说,所有的响应式数据都必须一开始就在状态机data内声明

var vm = new Vue({
  data: {
  	//不设置message
  },
  template: '<div>{{ message }}</div>'	//Vue 将警告你渲染函数正在试图访问不存在的 property。
})
// 动态设置 `message`,
vm.message = 'Hello!'

Vue无法监听复杂数据类型的property的内部变化,例如Array对象的某一项元素不通过数组方法发生改变、Object对象的某一项属性发生变化,Vue的Watcher是无法侦听到的,自然就不会触发视图重绘

Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。

对上面引用的解释为:Vue处理property变化是异步批量处理的,即同一数据property连续多次变更时,Vue只会把最后一次变更的结果Notify给Watcher,触发视图重绘

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值