数据代理
实现data的数据代理 // 保存options到vm上 this.$options = options || {}; // 保存data数据到vm上 _data var data = this._data = this.$options.data; // 保存vm var me = this; // 数据代理 // 代理data属性数据到vm上 // 遍历data数据中所有属性名成一个数组 Object.keys(data).forEach(function (key) { // 进行数据代理 me._proxyData(key); 关于me:每个函数都有this,通过me保存this(vm实例对象) });
// 代理data属性到vm上 _proxyData: function (key, setter, getter) { var me = this; //this指向vm实例对象 setter = setter || Object.defineProperty(me, key, { configurable: false, // 不能重新配置 enumerable: true, // 可以被遍历 get: function proxyGetter() { // 代理属性读操作 return me._data[key]; // 返回原属性的值 }, set: function proxySetter(newVal) { // 代理属性写操作 me._data[key] = newVal; // 设置原属性的值 }, }); }, |
代理computed计算属性到vm上 this._initComputed();
_initComputed: function () { var me = this; //vm实例对象 // 获取computed对象 var computed = this.$options.computed; if (typeof computed === "object") { Object.keys(computed).forEach(function (key) { // 数据代理 Object.defineProperty(me, key, { get: typeof computed[key] === "function" ? computed[key] : computed[key].get, // 计算属性不需要设置,计算属性当里面的值发生变化会自动更新 set: function () {}, }); }); } },
|
在创建mvvm实例对象的时候会传入一个option配置对象,在mvvm构造函数中把当前的配置对象保存到$options,把配置对象中的data保存在实例对象_data和变量data中,通过Object.keys()方法获取到data对象中的所有属性,并且遍历调用_proxyData方法实现数据代理,该方法内部通过Object.defineProperty方法将data中每个属性的值逐一添加到vm实例身上,并且重写了get和set方法,在外部通过vm.msg获取该属性值的时候,会将vm._data对应的msg进行返回,外部设置vm.msg值的时候,进入set方法,修改vm._data对应msg的值
代理配置对象中data的值后,会通过调用_initComputed方法将配置对象的computed属性代理到data中,也是通过Object.definePrototype方法,若代理属性的值是一个函数,将次函数作为get方法,若对应的是一个对象,对象身上的get对应的值作为此代理属性的get方法