Vue源码探究之状态初始化(4)
与 props 的处理类似,initData 函数的作用也是为了对数据建立观察的依赖关系,并且代理数据到私有变量 _data 上,另外包括了对 data 与其他配置对象属性的键名冲突的检测。
initComputed
// 设置computedWatcherOptions对象 const computedWatcherOptions = { computed: true } // 定义initComputed函数,接受实例vm,和computed对象 function initComputed (vm: Component, computed: Object) { // $flow-disable-line // 定义watchers和实例_computedWatchers属性,初始赋值空对象 const watchers = vm._computedWatchers = Object.create(null) // 是否是服务器渲染,computed属性在服务器渲染期间只能是getter // computed properties are just getters during SSR const isSSR = isServerRendering() // 遍历computed for (const key in computed) { // 获取用户定义的值 const userDef = computed[key] // 如果用户定义的是函数则赋值给getter否则j将userDef.get方法赋值给getter const getter = typeof userDef === 'function' ? userDef : userDef.get // 非生产环境抛出缺少计算属性错误警告 if (process.env.NODE_ENV !== 'production' && getter == null) { warn( `Getter is missing for computed property "${key}".`, vm ) } // 非服务器渲染下 if (!isSSR) { // 为计算属性创建内部监视器 // create internal watcher for the computed property. watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ) } // 组件定义的内部计算属性已经在组件的原型上定义好了 // 所以这里只要关注实例初始化时用户定义的计算属性 // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined // at instantiation here. // 键名非实例根属性时,定义计算属性,具体参照defineComputed函数 if (!(key in vm)) { defineComputed(vm, key, userDef) // 非生产环境下,检测与data属性名的冲突并给出警告 } else if (process.env.NODE_ENV !== 'production') { if (key in vm.$data) { warn(`The computed property "${key}" is already defined in data.`, vm) } else if (vm.$options.props && key in vm.$options.props) { warn(`The computed property "${key}" is already defined as a prop.`, vm) } } } } // 定义并导出defineComputed哈数 // 接收实例target,计算属性键名key,计算属性值userDef参数 export function defineComputed ( target: any, key: string, userDef: Object | Function ) { // 在非服务器渲染下设置缓存 const shouldCache = !isServerRendering() // 计算属性值是函数时 if (typeof userDef === 'function') { // 设置计算属性的getter,setter为空函数 sharedPropertyDefinition.get = shouldCache ? createComputedGetter(key) : userDef sharedPropertyDefinition.set = noop } else { // 当计算属性是对象时,设置计算属性的getter和setter sharedPropertyDefinition.get = userDef.get ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : userDef.get : noop sharedPropertyDefinition.set = userDef.set ? userDef.set : noop } // 非生产环境下,如果没哟定义计算属性的setter // 想设置计算属性时给出警告 if (process.env.NODE_ENV !== 'production' && sharedPropertyDefinition.set === noop) { sharedPropertyDefinition.set = function () { warn( `Computed property "${key}" was assigned to but it has no setter.`, this ) } } // 以重新设置的属性描述符为基础在实例对象上定义计算属性 Object.defineProperty(target, key, sharedPropertyDefinition) } // 定义createComputedGetter,创建计算属性getter // 目的是在非服务器渲染情况下建立计算属性的观察依赖, // 并根据其依赖属性返回计算后的值 function createComputedGetter (key) { return function computedGetter () { const watcher = this._computedWatchers && this._computedWatchers[key] if (watcher) { watcher.depend() return watcher.evaluate() } } }
内容版权声明:除非注明,否则皆为本站原创文章。