1、前言理解:
vue 一大特性数据驱动即数据更改驱动视图的变化 所以 数据变化监测是很重要的步骤 实现原理 js的Object.defineProperty 方法
2、观测Object数据 :
Object.defineProperty(obj, params, {enumerable: true,configurable: true,get(){console.log('price属性被读取了')return val},set(newVal){console.log('price属性被修改了')val = newVal}})
通过defineProperty 中的set 和 get 可以观测到某个属性的读和写的操作
3、通过递归观测所有的属性
/*** Observer类会通过递归的方式把一个对象的所有属性都转化成可观测对象*/export class Observer {constructor (value) {this.value = value// 给value新增一个__ob__属性,值为该value的Observer实例// 相当于为value打上标记,表示它已经被转化成响应式了,避免重复操作def(value,'__ob__',this)if (Array.isArray(value)) {// 当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])}}}/*** 使一个对象转化成可观测对象* @param { Object } obj 对象* @param { String } key 对象的key* @param { Any } val 对象的某个key的值*/function defineReactive (obj,key,val) {// 如果只传了obj和key,那么val = obj[key]if (arguments.length === 2) {val = obj[key]}if(typeof val === 'object'){new Observer(val)}Object.defineProperty(obj, key, {enumerable: true,configurable: true,get(){console.log(`${key}属性被读取了`);return val;},set(newVal){if(val === newVal){return}console.log(`${key}属性被修改了`);val = newVal;}})}
给value新增一个__ob__属性,值为该value的Observer实例。这个操作相当于为value打上标记,表示它已经被转化成响应式了,避免重复操作
然后判断数据的类型,只有object类型的数据才会调用walk将每一个属性转换成getter/setter的形式来侦测变化。 最后,在defineReactive中当传入的属性值还是一个object时使用new observer(val)来递归子属性,这样我们就可以把obj中的所有属性(包括子属性)都转换成getter/seter的形式来侦测变化。 也就是说,只要我们将一个object传到observer中,那么这个object就会变成可观测的、响应式的object。
