1、什么是数据代理?
所谓代理,就是中间人的意思。
var obj = {
a: {
b: 'hello'
}
}
console.log(obj.b) // undefined,obj下面没有b
obj.a.b = 'test' //正常只能这么修改属性b的值
//如果可以实现: obj.b = 'test',也就是obj代理a来修改b,这就是数据代理。
显然,vue实现了数据代理:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.9/vue.min.js"></script>
<script>
const vm = new Vue({
el:'#app',
data:{
name: 'hello'
}
})
console.log(vm.name) //vm代理了data,访问name值
vm.name = 'jack' //vm代理data,修改name值
console.log(vm)
</script>
2、如何实现数据代理?
思路很简单,我们可以将vm中的data的属性,在vm中重新定义一份即可,但下面这样实现是显然不行的:
function Vue(options){
this.$options = options
var data = this._data = this.$options.data
Object.keys(data).forEach(key=>{
this._proxy(key,data[key])
})
}
Vue.prototype = {
_proxy(key,val){
this[key] = val
}
}
const vm = new Vue({
el:'#app',
data:{
name: 'hello'
}
})
console.log(vm.name) //可以访问到hello
vm.name = 'jack' //vm中的name被修改了,但data里面的name并未修改,没有起到代理人的作用
console.log(vm)
虽然实现了读操作,但修改却无法实现。怎么办呢?
前面学过的Object.defineProperty方法就派上了用场:
function Vue(options){
this.$options = options
var data = this._data = this.$options.data
Object.keys(data).forEach(key=>{
this._proxy(key)
})
}
Vue.prototype = {
_proxy(key){
Object.defineProperty(this,key,{
configurable:false,
enumerable:true,
get(){
return this._data[key]
},
set(newVal){
this._data[key] = newVal
}
})
}
}
const vm = new Vue({
el:'#app',
data:{
name: 'hello'
}
})
console.log(vm.name) //可以访问到hello
vm.name = 'jack' //查看一下_data的name是否更新了?
console.log(vm._data.name) // jack
网友评论