Vue原理之为什么直接访问this可以获取到data和methods?

138 阅读1分钟

为什么直接访问this可以获取到data和methods?

当我们初学Vue时,会发现在new Vue实例时,直接在实例上可以直接访问到data和methods,有没有深入思考过框架是如何实现的呢?

const vm = new Vue({
    data: {
        name: '我是DG',
    },
    methods: {
        sayName(){
            console.log('sayName', this.name);
        }
    },
});
console.log('name', vm.name); // 输出我是DG
vm.sayName() // 直接执行vue的methods对象中的方法

原理解答

接下来,我们会用一个最简单的demo去理解其中的原理

  1. initMethod中,遍历methods对象,使用bind将每一个method拓展在pm实例
  2. data代理到_data中,将私有变量_data暴露给pm实例 以下代码是具体两点的实现:
var target = {
    enumerable: true,
    configurable: true,
    get: {},
    set: {}
};

function proxy (target, sourceKey, key) {
  target.get = function proxyGetter () {
    return this[sourceKey][key]
  };
  target.set = function proxySetter (val) {
    this[sourceKey][key] = val;
  };
  Object.defineProperty(target, key, target);
}

// 原理:遍历methods对象,使用bind将每一个method拓展在pm实例中
// 效果:pm实例中便具有了methods中的每个method
function initMethod(pm, methods) {
    Object.keys(methods).map(key => {
      pm[key] = methods[key].bind(pm);
    });
}

// 原理
// 将data代理到_data中,将私有变量_data暴露给pm实例
// 在_data中,我们同样会监听data的改变,做数据响应操作
function initData(pm,datas) {
    var _data = {};
    pm._data = datas;
    const key = Object.keys(datas)
    proxy(pm, "_data", key);
}

function Person(args) {
    var pm = this;
    pm.$options = args;
    const { methods = {}, data = {} } = args;
    initMethod(pm, methods); // 初始化method
    initData(pm, data); // 初始化data
    return pm;
}

const person = new Person({
data: {
  name: 'dk1'
},
methods: {
  sayName(){
    console.log('sayName1', this._data.name);
  }
}
});

person.sayName()

关键词:构造函数 this 指向 call、bind、apply Object.defineProperty 等等基础知识。

结语:学习框架思想会让我们将基础在实际的应用中巩固的更加牢固,构建自己的学习框架,应对问题时会更加有解决思路