数据驱动视图
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
更新真正的视图。
正因为拦截器是基于这七类数组方法来实现的,所以才会在官方文档里写上,当通过数组下标操作数组、修改数组长度时,是无法监测到变化的。