Vue原理
# Vue原理
# 1-数据响应式
# 实现方式
数据响应式就是一旦数据发生变化,我们可以得知这种变化并执行一些操作。
如何实现数据响应式?有两种方式:
- 对象属性拦截(Vue2.x)
Object.defineProperty
- 对象整体代理(Vue3.x)
Proxy
# Object.defineProperty()
该方法用于在对象上增加新属性或修改对象的现有属性。
参数:
对象
属性名或Symbol
配置对象,包含value、writable、enumerable、configurable、get()、set()
let data1 = {}
Object.defineProperty(data1, 'name', {
// 访问data1.name是自动调用set,得到get的返回值
get() {
console.log('访问了data1.name')
return 'corner'
},
// 修改name时调用的函数,传入新值
set(newVal) {
console.log('修改了data1.name,最新的值为:', newVal)
}
})
可以看到,此时修该属性name后再次访问却没有改变,还是打印了corner
,这是因为get和set之间没有任何联系。
# 联系get和set
解决上述问题的方式很简单,维护一个公共变量即可。
let _name = 'corner'
let data1 = {}
Object.defineProperty(data1, 'name', {
// 访问data1.name是自动调用set,得到get的返回值
get() {
console.log('访问了data1.name')
return _name
},
// 修改name时调用的函数,传入新值
set(newVal) {
console.log('修改了data1.name,最新的值为:', newVal)
_name = newVal
}
})
上面代码通过get和set操作公共变量_name
,这样就可以正常修改name属性了。
在Vue中我们是把响应式数据放在data(){return {}}
返回的对象里。
let data = {
isActive: true,
count: 0,
arr: ['new', 'hot']
}
Object.keys(data).forEach((key) => {
defineReactive(data, key, data[key])
})
function defineReactive(obj, key, value) {
Object.defineProperty(obj, key, {
get() {
return value
},
set(newVal) {
value = newVal
}
})
}
上面的代码就实现了对象的属性拦截。
注意:
Object.defineProperty()
劫持的是对象的属性,需要遍历属性,产生闭包,性能开销比较大。基于以上原因,开发中尽量不要在data里写无用的数据。
Vue3.x中,解决了Vue2.x中对于数据响应式处理的无端性能消耗,使用
Proxy
劫持了对象整体+惰性代理,用到了才进行响应式转换。