vue原理图
数据代理实现
废话不多说,我们先研究一下数据代理的实现。在这之前我们先来看看什么是数据代理:
<div id='app'></div>
<script>
const vm = new Vue({
el: '#app',
data: {
name: 'Jack'
}
});
//正常人思维,要想访问data中的name,我们的写法:
console.log(vm.data.name);
//vue的非正常用法:
console.log(vm.name);
//所谓的数据代理,也就是说我们能直接通过vue实例就可以“直接”拿到data中的数据
//也就是vue代理了data中的数据,所以我们在实际使用时总是可以通过this访问到data中的数据
</script>
那数据代理到底是如何实现的呢?其实一点都不神秘,就是通过Object.defineProperty(…)函数给data中所有的属性添加getter和setter方法,从而达到访问属性值和监视属性值的变化。好的,下面我们就来实现一下数据代理。
//ES6写法
class Vue {
constructor(options) {
//缓存配置项
this.$el = options.el || document.body;
this.$options = options;
const data = this.$data = options.data;
//劫持数据
this.hijackData(data);
}
hijackData(data) {
//拿到data中所有可枚举的属性
Object.keys(data).forEach(key => {
//递归遍历所有层次
this.hijackData(data[key]);
//代理数据
this.proxyData( key);
});
}
proxyData(key) {
//数据代理
Object.defineProperty(this, key, {
enumerable: true, //可枚举
configurable: false, //不能再配置
//添加getter
get() {
return this.$data[key]; //通过之前缓存的$data访问到data对象
//以后通过vue实例就可以直接访问到data中的数据了--> console.log(vm.name);
},
//添加setter
set(newVal) {
this.$data[key] = newVal;
//以后就可以监视到属性值的变化并更新其中的值--> vm.name = 'nice vue'
}
});
}
}
这一节先到这,下一节我们来实现数据响应化和模版/指令编译。
下一节:数据观察Observer