1. 实现
// MyVue.js
/**
* MyVue 构造函数
* @param { object } options 配置项
*/
function MyVue(options) {
this.vm = this; // 虚拟dom
this.data = options.data; // 数据
var self = this;
Object.keys(this.data).forEach(function(key){ // 遍历数据项
self.proxyKeys(key); // 下面我们会定义一个代理函数进行数据代理
});
observe(options.data); // 响应式数据
new Compile(options.el, this.vm); // 将数据加载到试图
return this;
}
/**
* 数据代理
*/
MyVue.prototype = {
proxyKeys: function(key) { // 添加原型方法进行数据代理,使MyVue.data[key] 可以直接使用 MyVue[key]进行访问
var self = this;
Object.defineProperty(this, key, { //配置描述符
enumerable: true, //可枚举
configurable: true, // 能否通过 delete 删除属性、能否修改属性的特性,或者将属性修改为访问器属性
get: function proxyGetter() { // getter函数
return self.data[key];
},
set: function proxySetter(val) { // setter函数
self.data[key] = val;
}
})
}
}
2. 测试
// 同级目录新建index.html文件 引入 MyVue.js
<body>
<div id="app">
<h1>{{title}}</h1>
<h2>{{name}}</h2>
<h3>{{content}}</h3>
</div>
</body>
<script src="Dep.js"></script>
<script src="observer.js"></script>
<script src="Watcher.js"></script>
<script src="Compile.js"></script>
<script src="SelfVue.js"></script>
<script>
var ele = document.querySelector('#name');
var myVue = new MyVue({
el:'#app',
data:{
title:'title-a',
name:'name-a',
content:'content-a'
}
})
window.setTimeout(function() {
myVue.title = 'title-b';
myVue.name = 'name-b';
myVue.content = 'content-b'
},2000);
</script>