Vue数据响应式
数据响应式,顾名思义就是根据数据的变化而产生响应的功能。在Vue 2中是如何实现数据响应的呢?从声明了new Vue到改变数据,页面UI响应的过程中发生了什么呢?这一切的一切,背后究竟隐藏着什么绝妙的设计思想?今天就让我来尝试理一理这背后的故事。
ES6语法中的getter和setter
多说无益,直接上代码。假设有如下对象:
let person = {
firstName: 'Harry',
lastName: 'Potter',
name() {
return this.firstName + this.lastName;
},
age: 6
};
//由于name是一个函数,因此想要得到person的name就必须用person.name()获取,如何在不使用括号的情况下获得person的name?
//在name前加上get,意为读这个函数
get name() {
return this.firstName + this.lastName;
}
//如何让name可以被赋值
//比如person.name = 'Ron Weasley',然后输入person.firstName显示'Ron'
//需要在person对象中加入set函数
set name(xxx) {
this.firstName = xxx[0]
this.lastName = xxx.slice(1)
}
//在输入person.name = 'Ron Weasley'后,就会call一下set函数
Object的defineProperty属性
详见MDN文档。 简言之就是创建一个虚拟属性。
Object.defineProperty(obj, prop, descriptor)
Vue 2 中奇妙的组合
使用defineProperty这个API,为Vue中的数据添加代理和监听。
先看下面一个例子。
let myData = {n:0}
let data_p = proxy({ data:myData }) //这里就是代理,对mydata的读写,全由另一个对象data_p来负责
function proxy({data}){
let value = data.n
Object.defineProperty(data, 'n', { //通过设置data的属性为n,来进行监听,之前的属性n被移除,这样当data变化时,就可以通过setter实现响应。这个过程就是监听。
get(){
return value
},
set(newValue){
if(newValue<0)return
value = newValue
}
})
const obj = {}
Object.defineProperty(obj, 'n', {
get(){
return data.n
},
set(value){
if(value<0)return
data.n = value
}
})
return obj //这里的obj也是一个代理
}
//set n的值为-1
再来看这行代码:
let data_p = proxy({ data:myData })
与Vue声明时的代码是不是有异曲同工之妙
let vm = new Vue({data: myData})
总结
Vue 2 通过Object.defineProperty实现数据响应,具体做法是给对象添加属性。添加getter和setter,用于对属性的监控。使用vm负责对数据的读写,vm就是数据的代理。