美文网首页让前端飞Web前端之路JavaScript 进阶营
Vue原理解析:Vue 实例如何实现代理 data 对象属性的访

Vue原理解析:Vue 实例如何实现代理 data 对象属性的访

作者: 张培跃 | 来源:发表于2019-08-17 20:37 被阅读7次

对于初学Vue.js的小伙伴而言,可能会认为Vue实例是一个很神奇的东西!因为它除了帮助我们完成双向绑定之外,还在某些细节方面为我们增加了一些理解上面的小烦恼!希望通过这篇文章能够为勤勉的你解惑~

看一段简单代码先:

new Vue({
    el:"#myApp",
    data:{
        userName:"laoWangTou",
        age:16
    },
    methods:{
        run(){
            // 输出结果:laoWangTou今年16岁了
            console.log(this.userName+"今年"+this.age+"岁了");
        }
    },
    created(){
        // this为什么可以调用methods的run方法?
        this.run();
    }
})

对于以上代码可能会有两个小疑问:
1、为什么钩子函数中的 this.run 可以调用到methods对像下的方法run?
2、为什么methods对象下的run方法可以通过this获得data下的属性?
要弄明白这两个问题首先你要明白下面几个点:

  • this即是通过Vue生成的实例vm
const vm = new Vue({
    el:"#myApp",
    created(){
        console.log(vm === this);// true
    }
})
  • $data与data是相等的
const data ={};
const vm = new Vue({
    el:"#myApp",
    data,
    created(){
        console.log(this.$data === data);// true
    }
})
console.log(vm.$data === data);// true
  • $data的属性被修改,vm实例下的属性也会发生相应的变化
const vm = new Vue({
    el:"#myApp",
    data:{
        userName:"laoWangTou",
        age:16
    },
    created(){
        this.$data.userName = "xiaoZhang"
        this.$data.age = 18;
        // 输出结果:xiaoZhang今年18岁了
        console.log(this.userName+"今年"+this.age+"岁了");
    }
})
// 输出结果:xiaoZhang今年18岁了
console.log(vm.userName+"今年"+vm.age+"岁了");

通过之前的两个疑问及得到的个结论,咱们可以先来个小猜测:

1、通过Vue生成的实例中有一属性为$data,其值为接收对象的data值
2、vm实例中代理了data的属性
3、methods下的方法赋值给了vm实例

于是,结合Vue.js的源码模拟出了以下较易理解的代码:

// 定义了一个构造函数
function Vue(options) {
    this.$data = options.data || {};
    this.initState(options);
}
Vue.prototype.initState = function (opts) {
    if(opts.data)
        this.initData(opts.data);
    if(opts.methods)
        this.initMethods(opts.methods);
    if(opts.created)
        opts.created.call(this);
}
Vue.prototype.initData = function (data) {
    var keys = Object.keys(data);
    var i = keys.length;
    while (i--){
        const key = keys[i];
        this.proxy("$data",key);
    }
}
Vue.prototype.initMethods = function (methods) {
    for (var key in methods) {
        this[key] = methods[key];
    }
}
Vue.prototype.proxy =function(sourceKey, key) {
    Object.defineProperty(this, key, {
        get() {
            return this[sourceKey][key]
        },
        set(val){
            this[sourceKey][key] = val;
        }
    });
};

验证:

const vm = new Vue({
    el:"#myApp",
    data:{
        userName:"laoWangTou",
        age:16
    },
    methods:{
        run(){
            // 输出结果:laoWangTou今年16岁了
            console.log(this.userName+"今年"+this.age+"岁了");
        }
    },
    created(){
        // this为什么可以调用methods的run方法?
        this.run();
    }
});
// 输出结果:laoWangTou今年16岁了
console.log(vm.userName+"今年"+vm.age+"岁了");

—————END—————

喜欢本文的朋友们,欢迎关注公众号 张培跃,收看更多精彩内容

相关文章

  • Vue.js 1.0 Official Guide Note

    Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...

  • vue 中script 标签 有哪些属性 (vue实例有哪些属性

    <1>数据访问 (1) $data: vue实例观察的数据对象,Vue实例代理了对其data对象属性的访问 (2)...

  • 01_双向数据绑定原理

    双向数据绑定原理:1)Vue实例上的所有data属性都会被Vue实例代理,而且是严格相等2)这些data属性在Vu...

  • vue学习笔记

    Vue学习笔记 Vue初始化对象 data和methods里面的属性都是Vue这个实例对象的代理属性,例:vm.m...

  • Vue中的data属性

    Vue 中的data Vue实例会代理data对象的属性, vm.$data.a相等于vm.a 以-和$开头的属性...

  • Vue第二节

    vue实例 每个 Vue 实例都会代理其 data 对象里所有的属性: 生命周期 链接beforeCreate c...

  • vue响应式原理

    原理 vue实例的data选项,vue 将遍历此对象的所有的属性,并使用 Object.defineProper...

  • vue实例属性

    vm.$data 类型:Object【对象】详细:Vue 实例观察的数据对象。Vue 实例代理了对其 data 对...

  • vue-实例属性

    vm.$data 类型:Object 详细: Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属...

  • Vue原理解析:Vue 实例如何实现代理 data 对象属性的访

    对于初学Vue.js的小伙伴而言,可能会认为Vue实例是一个很神奇的东西!因为它除了帮助我们完成双向绑定之外,还在...

网友评论

    本文标题:Vue原理解析:Vue 实例如何实现代理 data 对象属性的访

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