vue简版源码 MVVM篇
相关链接:Observer篇 、Compile篇 、 Watcher篇
有很多小伙伴在整理vue数据双向绑定的时候,是知其然而不知其所以然,这说到底这是对vue源码的一种不理解,下面我给大家每一句都加上注释,方便大家理解。
准备:
<script src="./mvvm-master/js/observer.js"></script> // observer 观察者
<script src="./mvvm-master/js/compile.js"></script> // compile 模板解析
<script src="./mvvm-master/js/watcher.js"></script> // watcher 订阅者
<script src="./mvvm-master/js/mvvm.js"></script> // 实现代理
<script>
// const vm = new Vue({
const vm = new MVVM({
el: "#app",
data: {
name: "aa",
age: {
a1: 18
}
}
});
</script>
MVVM 源码
function MVVM(options) {
//给实例新增一个$options属性,.并且把传递过来的配置进行暂存
this.$options = options;
//在实例上新增一个_data 保存传递过来的data数据
var data = this._data = this.$options.data;
//保存this 为了之后使用this的时候保证this指向的正确性
var me = this;
//通过Object.keys取出data中每一项数据的属性名,然后遍历调用_proxy方法
Object.keys(data).forEach(function(key) {
// 数据代理
me._proxy(key);
});
//为data所有数据进行劫持 结合订阅发布模式 data :传递过来的data数据 , this:MVVM 实例 vm(构造函数中this指向构造函数的实列)
observe(data, this);
// 增加模版解析 new 一个Copile实例,并传入参数 参数一:el传过来的节点,或者把整个body传过去 参数二: MVVM 实例 vm
this.$compile = new Compile(options.el || document.body, this)
}
MVVM.prototype = {
$watch: function(key, cb, options) {
new Watcher(this, key, cb);
},
// 实现数据代理 key : 传过来的每一项的属性名
_proxy: function(key) {
var me = this; // 暂存this 保证this的指向正确 这里的this还是 MVVM 实例vm
//通过defineProperty方法在实例(vm)上新增所有与data中属性所对应属性,并且为该属性添加get和set方法
Object.defineProperty(me, key, {
configurable: false, // 是否可设置 为false 不能
enumerable: true, // 是否可枚举(遍历) true 可以
get: function proxyGetter() {
// 实现了vm 代理data中数据的读操作
return me._data[key]; // 返回 _data中的每一项的属性值
},
set: function proxySetter(newVal) { // newVal :在页面上赋值操作时,获取到的最新的值
// 实现了vm 代理data中数据的写操作
me._data[key] = newVal; // 给 _data中的每一项的属性 赋予最新的值
}
});
}
};