Vue响应式依赖收集原理分析-vue高级必备

背景

在 Vue 的初始化阶段,_init 方法执行的时候,会执行 initState(vm) ,它的定义在 src/core/instance/state.js 中。在初始化 data 和 props option 时我们注意 initProps 和 initData 方法中都调用了 observe 方法。通过 observe (value),就可以将数据变成响应式。

export function initState (vm: Component) {vm._watchers = []const opts = vm.$optionsif (opts.props) initProps(vm, opts.props)if (opts.methods) initMethods(vm, opts.methods)if (opts.data) {initData(vm)} else {observe(vm._data = {}, true /* asRootData */)}if (opts.computed) initComputed(vm, opts.computed)if (opts.watch && opts.watch !== nativeWatch) {initWatch(vm, opts.watch)}
} 
  • initPropsif (value === undefined) {observe(value);} * initDataobserve(data, true /* asRootData */) 目标

  • 理解 Vue 数据响应式原理,了解响应式原理依赖收集的过程

  • 了解在什么阶段会触发依赖收集

源码解读

入口函数:observe

observe 方法定义在 src/core/observer/index.js 中。如果是一个非 VNode 的对象类型的数据,它会尝试给这个值去创建一个 observer 实例,如果创建成功,返回新的 observer。或者如果 ob 已经存在了,就会直接返回一个现有的 observer。

/** * 尝试给这个值去创建一个 observer 实例,如果创建成功,返回新的 observer* 或者如果值已经有了,返回一个现有的 observer * @param {*} value* @param {boolean} asRootData* @returns Observer | void */
export function observe (value: any, asRootData: ?boolean): Observer | void {if (!isObject(value) || value instanceof VNode) {return}let ob: Observer | void// 如果 value 已经有 observer,就返回现有的 observer// 否则如果不是服务器渲染,value是数组或者对象,value 是可扩展的,value 不是 vue 实例,就创建一个新的 observerif (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {ob = value.__ob__} else if (shouldObserve &&!isServerRendering() &&(Array.isArray(value) || isPlainObject(value)) &&Object.isExtensible(value) &&!value._isVue) {ob = new Observer(value)}// 如果是根组件,vmCount 不为0if (asRootData && ob) {ob.vmCount++}return ob
} 

通过 new Observer(value) 可以给 value 创建一个 observer 实例,那么 Observer 类的定义和作用是什么?在同一个文件下可以看到 class Observer 是如何定义的。

相关vue实战视频讲解:进入学习

class Observer

Observer 方法定义在 src/core/observer/index.js 中。在它的构造函数中,首先实例化 Dep 对象(主要用来存放它的 watcher列表),接着通过执行 def 函数把自身实例添加到数据对象 value 的 ob 属性上,所以存在 ob 属性意味着已经被观察过。最后判断 value 为数组的情况下,会数组项遍历,给数组的每一项创建一个 observe 实例;如果是对象,那么遍历所有的属性,通过Object.defineProperty修改getter/setters。

/** * Observer 类和每个响应式对象关联。 * observer 会转化对象的属性值的 getter/setters 方法收集依赖和派发更新。 */
export class Observer {value: any;dep: Dep;vmCount: number; // number of vms that have this object as root $dataconstructor(value: any) {this.value = valuethis.dep = new Dep() // 存放 Observer 的 watcher 列表this.vmCount = 0def(value, '__ob__', this) // __ob__ 指向自身 observe 实例,存在 __ob__ 属性意味着已经被观察过// 如果是数组if (Array.isArray(value)) {// hasProto = '__proto__' in {} 判断对象是否存在 __proto__ 属性if (hasProto) {// 如果有 __proto__,就将 value.__proto__ 指向 arrayMethodsprotoAugment(value, arrayMethods)} else {// 否则,就遍历 arrayMeth
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值