一、数据代理的分析
- 数据代理:通过一个对象代理另一个对象中的属性操作,包括读和写的操作。
- vue的数据代理:
data
对象的所有属性操作,读和写的操作都是通过vm
对象代理来操作的。
- 好处:通过
vm
对象就可以方便的操作data
中的数据。
- 数据代理的实现过程:
- 通过
Object.defineProperty(vm, key, {})
给vm
添加与data
对象的属性对应的属性
- 所有添加的属性都包括
get
和set
方法
- 在
get
和set
方法中去操作data
中对应的属性
- 数据代理的关键过程:
_proxy: function (key) {
var me = this;
Object.defineProperty(me, key, {
configurable: false,
enumerable: true,
get: function proxyGetter() {
return me._data[key];
},
set: function proxySetter(newVal) {
me._data[key] = newVal;
}
});
}
- 在
vue
的实现过程中,是通过new Vue
的实例,而在我们实现的过程是通过new MVVM
的实例,创建构造函数,核心是通过vm
代理数据操作,vm.name
是代理数据读的操作,而vm.name="李四"
,是可以代理对数据写的操作,通过vm._data.name
就可以拿到值,代码如下:
const vm = new MVVM({
el: "test",
data: {
name: "张三"
}
});
console.log(vm.name, vm);
vm.name = "李四";
console.log(vm._data.name, vm.name, vm);
二、数据代理的实现:
- MVVM.js:
function MVVM(options) {
this.$options = options;
var data = this._data = this.$options.data;
var me = this;
Object.keys(data).forEach(function (key) {
me._proxy(key);
});
observe(data, this);
this.$compile = new Compile(options.el || document.body, this)
}
MVVM.prototype = {
$watch: function (key, cb, options) {
new Watcher(this, key, cb);
},
_proxy: function (key) {
var me = this;
Object.defineProperty(me, key, {
configurable: false,
enumerable: true,
get: function proxyGetter() {
return me._data[key];
},
set: function proxySetter(newVal) {
me._data[key] = newVal;
}
});
}
};
- 数据代理MVVM的实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>数据代理的MVVM实现</title>
</head>
<body>
<div id="test"></div>
</body>
<script type="text/javascript" src="./js/mvvm/compile.js"></script>
<script type="text/javascript" src="./js/mvvm/mvvm.js"></script>
<script type="text/javascript" src="./js/mvvm/observer.js"></script>
<script type="text/javascript" src="./js/mvvm/watcher.js"></script>
<script>
const vm = new MVVM({
el: "test",
data: {
name: "张三"
}
});
console.log(vm.name, vm);
vm.name = "李四";
console.log(vm._data.name, vm.name, vm);
</script>
</html>
- 关于
vue
的源码分析,我在github
上建立了一个项目,项目地址如下https://github.com/jiuchengTk279/vueSourceCode.git
,欢迎大家访问下载,也希望可以多给予一些建议交流。