vue源码分析(二):数据代理

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。