vue2 - 数据响应式原理详解

数据驱动视图

		data(){
			return {
			obj:{},
			arr:[]
			......
			}
		}
  • 写在data里的这些数据,当在某些情况下数据改变的时候,视图也会跟着改变,重新渲染一次。
  • 在vue2文档里有下面这些话:

对于对象

  • Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
  • 对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property
  • 您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:
  • 有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。

对于数组

  • Vue 不能检测以下数组的变动:

    (1)当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue

    (2)当你修改数组的长度时,例如:vm.items.length = newLength

  • 你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名

  • 为了解决第二类问题,你可以使用 splice

    为什么会出现以上现象呢?

    那就一起来看看数据响应式到底是如何来实现的吧!

object数据的响应式

简单介绍Object.defineProperty()

  • 该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

  • 语法

    Object.defineProperty(obj, prop, descriptor)
    
    参数含义
    obj要定义属性的对象
    prop要定义或修改的属性的名称或 Symbol
    descriptor要定义或修改的属性描述符

    返回值 :被传递给函数的对象。

  • 使用方法:

    var obj = {};
    Object.defineProperty(
    	obj,		//	目标对象
    	'key',		//	需要操作的目标对象的属性名
    	descriptor	//	描述符
    );	
    
  • 描述符 descriptor 常用的属性解释如下:

    属性含义
    configurable当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false
    enumerable当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false
    get属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 默认为 undefined
    set属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined
  • 其余语法描述见连接:MDN-Object.defineProperty()

对象响应式概述

  • 遍历对象的所有属性,通过Object.defineProperty() 让每个属性变得可监测:当读取属性、修改属性都可以做一些额外操作。
  • 读取数据(getter)的时候:在dep中添加相关的watcher。
  • 设置/修改数据(setter)的时候:由dep通知watcher更新真正的视图。

Array数组的响应式

因为Object数据劫持用的是对象原型上的方法Object.defineProperty() ,而Array无法使用这个方法,所以需要用另一套变化侦测机制。

数组响应式概述

  • Vue中创建了一个数组方法拦截器,在拦截器内部重写操作数组的一些方法,当数组实例使用数组方法改变数组数据时,使用拦截器内重写的方法
  • 即:克隆一份内置的七个改变原数组push、pop、shift、unshift、splice、sort、reverse的操作数组的方法。
  • 在克隆的这一份方法上,能够监测到数据变化,做一些额外操作。
  • 添加新数据的时候:需要进行数据响应式的处理,由dep通知watcher更新真正的视图。
  • 删除数据的时候:由dep通知watcher更新真正的视图。

正因为拦截器是基于这七类数组方法来实现的,所以才会在官方文档里写上,当通过数组下标操作数组、修改数组长度时,是无法监测到变化的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值