Vue2响应式数据原理

894 阅读2分钟

要谈vue的响应式数据原理,首先要了解javascript中Object.defineProperty()这个接口可以做什么。 在js中,除了基本类型就是对象类型的数据,所有对象类型又都继承自Object这个初始类。因此所有的对象类型数据都具有Object原型上的方法。

每一种对象类型中的每个属性(x)都有4个描述符来描述这个属性(x)的可配置性(configruable),值(value)、可枚举性(enmurable)、可更改性(writable)。具体每个属性代表什么含义可以访问MDN去查看。

此外,js还提供了两个函数作为每个属性的描述属性:get,set

get在访问属性的时候会被调用到,如果有get函数,则访问属性会忽略value的值,返回get函数返回的值。

如果有set函数,对属性赋值的时候会执行此函数。会传入赋值时的 this 对象。

vue2的响应式原理依赖于这个接口的实现

在实例化vue组件(实例)的时候,会在create之前对data函数中返回的数据进行一次响应式处理。对data中的每个属性进行遍历。

// 伪代码
for(let item in data){
	Object.defineProperty(data,item,{
		get(){
			dep(); // 这里收集依赖
		},
		set(val){
			update(); // 更新数据的时候触发更新
			item = val;
		}
	})
}

由于性能关系,vue2没有对数组进行遍历,通过下标对数组进行赋值是无法监控到数组的变化的。但是vue2对数组的方法进行了拦截改写,进而达到响应式的目的。其中有(split,push,shift,unshift,reverse)。调用其中的任何一个方法都可以达到响应式的目的。

vue 还提供了set接口动态的增加响应式数据到根节点(data)上。

vue.set(data,target)内部调用了Object.defineProperty(data,target,options)函数将属性增加到根节点上,并且对这个属性用Object.defineProperty()重写其get,set,在重写的同时做依赖收集。进而达到新增数据的响应式效果