functioninitData(vm){let data = vm.$options.data
// 获取到用户传入的options 取到data属性, data的写法如果是函数形式 那么就使用.call指向传入的vm 拿到返回值 // 如果不是函数形式就是对象了不处理, 将数据绑定到data 和 vm._data(绑定到_data统一管理)上
data = vm._data =typeof data ==='function'?getData(data, vm): data ||{}if(!isPlainObject(data)){
data ={}
process.env.NODE_ENV!=='production'&&warn('data functions should return an object:\n'+'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
vm
)}const keys = Object.keys(data)const props = vm.$options.props
const methods = vm.$options.methods
let i = keys.length
while(i--){const key = keys[i]// 检查data里的数据是否与methods里的方法名冲突if(process.env.NODE_ENV!=='production'){if(methods &&hasOwn(methods, key)){warn(`Method "${key}" has already been defined as a data property.`,
vm
)}}// 检查data里的数据是否与props里的数据冲突if(props &&hasOwn(props, key)){
process.env.NODE_ENV!=='production'&&warn(`The data property "${key}" is already declared as a prop. `+`Use prop default value instead.`,
vm
)}elseif(!isReserved(key)){// 如果不是保留字段,将data里的属性代理到vm实例上,使得可以通过this获取proxy(vm,`_data`, key)}}// 响应式处理第一步observe(data,true/* asRootData */)}
classObserver{
value;
dep;vmCount: number;// number of vms that have this object as root $dataconstructor(value){this.value = value
// 实例化一个dep,即Observer都会有一个Dep依赖this.dep =newDep()this.vmCount =0//添加'__ob__'def(value,'__ob__',this)// 数组需要单独处理if(Array.isArray(value)){if(hasProto){// 如果是现代的浏览器,复杂类型数据有原型,调用arrayMethods,重写相关方法,具体见下边protoAugment(value, arrayMethods)}else{// 如果是老旧浏览器,没有原型,直接给数组上的方法给重写替换掉copyAugment(value, arrayMethods, arrayKeys)}// 调用数组观察方法this.observeArray(value)}else{// 对象的响应式处理this.walk(value)}}// 对象响应式处理:遍历所有属性,并为每个属性添加geeter/setter。walk(obj: Object){const keys = Object.keys(obj)for(let i =0; i < keys.length; i++){defineReactive(obj, keys[i])}}// 数组观察方法observeArray(items: Array<any>){for(let i =0, l = items.length; i < l; i++){observe(items[i])}}}
// 获取数组的原型Array.prototypeconst arrayProto =Array.prototype
// 创建一个空对象arrayMethods,并将arrayMethods的原型指向arrayProtoexportconst arrayMethods = Object.create(arrayProto)// 这些方法需要重写覆盖const methodsToPatch =['push','pop','shift','unshift','splice','sort','reverse']
methodsToPatch.forEach(function(method){const original = arrayProto[method]def(arrayMethods, method,functionmutator(...args){// 执行原始行为的逻辑const result =original.apply(this, args)const ob =this.__ob__
let inserted
switch(method){case'push':case'unshift':
inserted = args
breakcase'splice':
inserted = args.slice(2)break}// 新加入的元素做响应式处理if(inserted) ob.observeArray(inserted)// 内部的dep去通知更新
ob.dep.notify()return result
})})
对象响应式处理
在Observer类里边,walk方法里调用了defineReactive方法
获取数据时:在dep中添加相关的watcher
设置数据时:再由dep通知相关的watcher去更新
src\core\observer\index.js
functiondefineReactive(obj,key,valcustomSetter,shallow){const dep =newDep(); // 每个key都会实例化一个Dep// 获取属性相关描述const property = Object.getOwnPropertyDescriptor(obj, key)// configurable为false时,该属性相关的配置不能再被更改,也不能被删除if(property && property.configurable ===false){return}const getter = property && property.get
const setter = property && property.set
if((!getter || setter)&& arguments.length ===2){
val = obj[key]}let childOb =!shallow &&observe(val)// 拦截对obj[key]的获取和设置
Object.defineProperty(obj, key,{enumerable:true,configurable:true,// 拦截对obj[key]的获取操作get:functionreactiveGetter(){// 获取obj[key]的值const value = getter ?getter.call(obj): val
// 依赖收集// 如果存在,则说明此次调用触发者是一个Watcher实例if(Dep.target){// 依赖关系的创建,建立dep和Dep.target之间的依赖关系(把dep添加到watcher中,也将watcher添加到dep中)
dep.depend()if(childOb){// 建立是ob内部的dep和Dep.target之间的依赖关系,也就是嵌套对象的依赖收集
childOb.dep.depend()if(Array.isArray(value)){// 如果是数组,数组内部的所有项都需要做依赖收集处理dependArray(value)}}}return value
},// 拦截对obj[key]的设置操作set:functionreactiveSetter(newVal){const value = getter ?getter.call(obj): val
// 如果新值和老值相等则不做处理 直接返回if(newVal === value ||(newVal !== newVal && value !== value)){return}// 如果setter不存在,说明只能获取不能设置,也直接返回if(getter &&!setter)return// 设置为新的值if(setter){setter.call(obj, newVal)}else{
val = newVal
}// 对新值也做响应式处理
childOb =!shallow &&observe(newVal)// 通知更新
dep.notify()}})}
收集对数组元素的依赖项
functiondependArray(value: Array<any>){for(let e, i =0, l = value.length; i < l; i++){
e = value[i]
e && e.__ob__ && e.__ob__.dep.depend()if(Array.isArray(e)){dependArray(e)}}}