美文网首页web前端
vue源码分析(二):数据代理

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

作者: 姜治宇 | 来源:发表于2020-08-31 12:20 被阅读0次

    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
    

    相关文章

      网友评论

        本文标题:vue源码分析(二):数据代理

        本文链接:https://www.haomeiwen.com/subject/adlusktx.html