You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// src/core/instance/state.jsfunctioninitData(vm: Component){letdata=vm.$options.datadata=vm._data=typeofdata==='function'
? data.call(vm)
: data||{}if(!isPlainObject(data)){data={}process.env.NODE_ENV!=='production'&&warn('data functions should return an object.',vm)}// proxy data on instanceconstkeys=Object.keys(data)constprops=vm.$options.propsleti=keys.lengthwhile(i--){if(props&&hasOwn(props,keys[i])){process.env.NODE_ENV!=='production'&&warn(`The data property "${keys[i]}" is already declared as a prop. `+`Use prop default value instead.`,vm)}else{proxy(vm,keys[i])}}// observe dataobserve(data)data.__ob__&&data.__ob__.vmCount++}
// src/core/observer/index.js
export classObserver{value: any;
dep: Dep;
vmCount: number;// number of vms that has this object as root $dataconstructor(value: any){this.value=valuethis.dep=newDep()this.vmCount=0def(value,'__ob__',this)if(Array.isArray(value)){constaugment=hasProto
? protoAugment
: copyAugmentaugment(value,arrayMethods,arrayKeys)this.observeArray(value)}else{this.walk(value)}}/** * Walk through each property and convert them into * getter/setters. This method should only be called when * value type is Object. */walk(obj: Object){constkeys=Object.keys(obj)for(leti=0;i<keys.length;i++){defineReactive(obj,keys[i],obj[keys[i]])}}/** * Observe a list of Array items. */observeArray(items: Array<any>){for(leti=0,l=items.length;i<l;i++){observe(items[i])}}}
作者:holyZheng
转载请注明出处
vue的响应式数据绑定
vue中的响应式数据绑定是通过数据劫持和观察者模式来实现的。当前学习源码为vue2.0
源码关键目录
当我们实例化一个vue应用的时候,会伴随着各种的初始化工作,相关的初始化工作代码在init.js文件中
在这里可以看到对state的初始化工作initState()
可以看到这里有对各种sate的初始化工作,我们看initData()
这里做了一点判断,判断data方法是否返回的是一个对象,以及props中是否有与data中重名的属性,最后会调用observe对data进行监听,看一下observe
可已看到这里也是做了一点判断,如果有__ob__属性的话就用它,或者如果data是数组或对象或可扩展对象的话,就为它新建一个Observer,看一下Observer
判断data是不是数组,如果是数组就对数组元素再去调用observe方法做同样的处理,如果不是,就调用walk去劫持该数据,对数据的劫持主要再defineReactive方法中,正如函数名,让数据变得响应式。看一下defineReactive方法
遍历状态,修改状态的getter和setter,当页面上对应状态被首次渲染的时候,会为页面上每一个使用到data的地方新建一个watcher,并将当前watcher保存到全局变量Dep.target中,在对应data的getter中就会调用Dep.depend方法,将当前的watcher添加到当前的Dep中,一个Dep对应一个或多个watcher,着取决于,此状态被使用的数量。当data被修改时,对应的setter就会被触发,会调用对应的Dep中的notify方法,通知所有观察者,进行更新。
这里出现了两个定的类:Dep和Watcher,其中Dep管理观察者,Wathcer代表观察者
先看一下Dep
看一下watcher.js
总结
vue的响应式数据绑定主要依赖Object.defineProperty和观察者模式。
src
文件夹下的core
文件夹下的instance
和observer
文件夹内The text was updated successfully, but these errors were encountered: