Vue 源码解读-数据响应系统
栏目: JavaScript · 发布时间: 5年前
内容简介:作者:呆恋小喵我的后花园:我的 github:
data 对象初始化
-
通过 vm.$options.data 函数获取 data 对象
-
校验 data 对象是否为 纯对象
-
检验 data 对象与 props 对象 冲突键
-
检验 methods 对象与 data 对象 冲突键
-
在 Vue 实例添加 代理 访问 data 对象的同名属性
-
调用 observe 函数开启 响应式
数据响应系统
-
避免收集 重复 依赖
-
深度 观测
-
处理 边界 条件
observe 工厂函数
export function observe (value: any, asRootData: ?boolean): Observer | void { if (!isObject(value) || value instanceof VNode) { return } let ob: Observer | void // 避免重复观测 if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__ } else if ( // 是否开启观测 shouldObserve && // 是否服务端渲染 !isServerRendering() && // 待观测对象是否为数组或纯对象 (Array.isArray(value) || isPlainObject(value)) && // 待观测对象是否可扩展 Object.isExtensible(value) && // 避免观测 Vue 实例 !value._isVue ) { ob = new Observer(value) } if (asRootData && ob) { ob.vmCount++ } return ob }
observer 构造函数
export class Observer { // 待观测对象 value: any; // 待观测对象依赖收集“筐” dep: Dep; vmCount: number; constructor (value: any) { this.value = value this.dep = new Dep() this.vmCount = 0 // 为待观测对象定义不可枚举 __ob__ 属性 def(value, '__ob__', this) // 处理数组 if (Array.isArray(value)) { const augment = hasProto ? protoAugment : copyAugment // 调用变异函数时执行依赖 augment(value, arrayMethods, arrayKeys) // 开启深度观测 this.observeArray(value) // 处理纯对象 } else { this.walk(value) } } 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]) } } }
defineReactive 函数
get 函数
-
返回 属性值
-
收集 依赖
set 函数
-
设置 属性值
-
触发 依赖
export function defineReactive ( obj: Object, key: string, val: any, customSetter?: ?Function, shallow?: boolean ) { // 待观测对象依赖收集“筐” const dep = new Dep() // 属性描述对象 const property = Object.getOwnPropertyDescriptor(obj, key) // 属性描述对象是否可配置 if (property && property.configurable === false) { return } // 缓存原 setter、getter const getter = property && property.get const setter = property && property.set if ((!getter || setter) && arguments.length === 2) { val = obj[key] } // 开启深度观测 let childOb = !shallow && observe(val) // 重定义 setter、getter Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { // 保证原 getter 正常运作且返回属性值 const value = getter ? getter.call(obj) : val // 依赖是否存在 if (Dep.target) { // 收集依赖至 dep “筐”,属性值被修改时执行依赖 dep.depend() if (childOb) { // 收集依赖至 childOb.dep “筐”,添加新属性时执行依赖 childOb.dep.depend() if (Array.isArray(value)) { // 因数组索引无 get,逐个收集每一数组元素依赖 dependArray(value) } } } return value }, set: function reactiveSetter (newVal) { // 获取原属性值 const value = getter ? getter.call(obj) : val // 属性值是否更新 if (newVal === value || (newVal !== newVal && value !== value)) { return } // 非生产环境打印辅助信息 if (process.env.NODE_ENV !== 'production' && customSetter) { customSetter() } // 保证原 setter 正常运作且设置属性值 if (setter) { setter.call(obj, newVal) } else { val = newVal } // 开启深度观测 childOb = !shallow && observe(newVal) // 执行依赖 dep.notify() } }) }
数组变异函数拦截
import { def } from '../util/index' const arrayProto = Array.prototype export const arrayMethods = Object.create(arrayProto) const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] methodsToPatch.forEach(function (method) { // 缓存原变异函数 const original = arrayProto[method] // 定义与变异函数同名的拦截函数 def(arrayMethods, method, function mutator (...args) { // 调用原变异函数 const result = original.apply(this, args) const ob = this.__ob__ let inserted switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = args.slice(2) break } // 观测新增元素 if (inserted) ob.observeArray(inserted) // 执行依赖 ob.dep.notify() return result }) })
作者:呆恋小喵
我的后花园: https://sunmengyuan.github.io/garden/
我的 github: https://github.com/sunmengyuan
原文链接: https://sunmengyuan.github.io/garden/2019/02/01/vue-observer.html
以上所述就是小编给大家介绍的《Vue 源码解读-数据响应系统》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- flask 源码解析6:响应
- 从源码解析vue的响应式原理-响应式的整体流程
- Vue 源码(一):响应式原理
- vue响应式系统源码解析
- 从源码解析vue的响应式原理
- Vue源码分析系列五: 响应式原理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Collective Intelligence实战
阿拉克 / 2010-9 / 58.00元
《Collective Intelligence实战》内容简介:在互联网上,利用用户的集体智慧是成功的关键。集体智慧是一种新兴的编程技术,可让您从人们访问web和与web交互的过程中找到有价值的模式、发现这些访问者之间的关系和确定他们的个人偏好及习惯等。《collective Intelligence实战》首先介绍了集体智慧的原则和构建更具交互性网站的思想,然后通过示例开发了一个直接可用的基于Ja......一起来看看 《Collective Intelligence实战》 这本书的介绍吧!