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
defineReactive 就是定义对象上的响应性属性的方法
它是通过 Object.defineProperty 为数据定义上 getter\setter 方法
该方法会形成一个闭包,实例化一个私有的 Dep 实例进行该对象的依赖收集,改变数据触发 setter 的时候会由 Dep 通知所有的 Watcher 观察者对象进行视图的更新。
/** * Define a reactive property on an Object. * 定义对象上的响应性属性。 */exportfunctiondefineReactive(obj: Object,key: string,val: any,customSetter?: ?Function,shallow?: boolean){// 实例化一个私有的 dep 提供给后面新定义的 getter/setter 调用constdep=newDep()// 获取对象上对应属性的描述符constproperty=Object.getOwnPropertyDescriptor(obj,key)// 描述符可更改if(property&&property.configurable===false){return}// cater for pre-defined getter/setters// 如果已定义过 getter/setter 则先将其缓存下来 在后续覆盖定义之后再执行constgetter=property&&property.getconstsetter=property&&property.setif((!getter||setter)&&arguments.length===2){val=obj[key]}// 将子对象再进行 observe 监听 并缓存返回的实例letchildOb=!shallow&&observe(val)// 进行响应式定义Object.defineProperty(obj,key,{enumerable: true,configurable: true,get: functionreactiveGetter(){// 先执行原有的 getter 方法constvalue=getter ? getter.call(obj) : valif(Dep.target){// 依赖收集dep.depend()if(childOb){// 子对象进行依赖收集// 其实就是将同一个watcher观察者实例放进了两个depend中// 一个是正在本身闭包中的depend,另一个是子元素的dependchildOb.dep.depend()if(Array.isArray(value)){dependArray(value)}}}returnvalue},set: functionreactiveSetter(newVal){// 通过 getter 方法获取旧值constvalue=getter ? getter.call(obj) : val/* eslint-disable no-self-compare */if(newVal===value||(newVal!==newVal&&value!==value)){return}/* eslint-enable no-self-compare */if(process.env.NODE_ENV!=='production'&&customSetter){customSetter()}// #7981: for accessor properties without setter// 对于没有setter的访问器属性if(getter&&!setter)returnif(setter){// 先执行原有的 setter 方法setter.call(obj,newVal)}else{val=newVal}// 对新值再进行监听childOb=!shallow&&observe(newVal)// 由 dep 通知所有 watcherdep.notify()}})}
在 getter 进行依赖收集的过程中,对于数组元素还会进行深度递归的依赖收集
/** * Collect dependencies on array elements when the array is touched, since * we cannot intercept array element access like property getters. */functiondependArray(value: Array<any>){for(lete,i=0,l=value.length;i<l;i++){e=value[i]// 进行依赖收集e&&e.__ob__&&e.__ob__.dep.depend()// 若值为数组 则 继续递归收集if(Array.isArray(e)){dependArray(e)}}}
/** * Attempt to create an observer instance for a value, * returns the new observer if successfully observed, * or the existing observer if the value already has one. *//** * 尝试为一个值创建一个 Observer 实例(__ob__), * 如果值已经有了 Observer 实例,则返回现有 Observer 实例。 * 如果没有且成功监听,则返回新的 Observer, */exportfunctionobserve(value: any,asRootData: ?boolean): Observer|void{// 判断 非对象|vnode 直接返回if(!isObject(value)||valueinstanceofVNode){return}letob: Observer|void// 判断是否存在 Observer 实例if(hasOwn(value,'__ob__')&&value.__ob__instanceofObserver){// 存在直接赋值ob=value.__ob__}elseif(shouldObserve&&!isServerRendering()&&(Array.isArray(value)||isPlainObject(value))&&// 数组|普通对象Object.isExtensible(value)&&// 可扩展的对象!value._isVue){// 不存在则进行实例化ob=newObserver(value)}if(asRootData&&ob){// 根数据会进行计数ob.vmCount++}returnob}
defineReactive
defineReactive
就是定义对象上的响应性属性的方法它是通过
Object.defineProperty
为数据定义上getter\setter
方法该方法会形成一个闭包,实例化一个私有的
Dep
实例进行该对象的依赖收集,改变数据触发setter
的时候会由Dep
通知所有的Watcher
观察者对象进行视图的更新。在
getter
进行依赖收集的过程中,对于数组元素还会进行深度递归的依赖收集observe方法
这个方法会返回一个Observer实例,同时将视力绑定到响应式数据的__ob__属性上,并不会重复绑定
相关源码
下一篇解读
Observer
类和数组的响应式实现The text was updated successfully, but these errors were encountered: