mvvm.js
function Jiechi(options = {}) {
this.$options = options;//将所有属性挂载到options上
var data = this._data = this.$options.data;
observer(data);
// 这里解决的是把所有data属性存放到实例上面可以让实例直接访问属性。现在是jiechi._data.a要转换成比如jiechi.a
for (let key in data) {
Object.defineProperty(this, key, {
enumerable: true,
get() {
return this._data[key];
}, set(newVal) {
this._data[key] = newVal;
}
})
}
new Compile(options.el, this)
}
function Compile(el, vm) {
//el 表示替换的范围
vm.$el = document.querySelector(el);
console.log(vm.$el);
// 创建文档碎片把属性都放到里面
let fragment = document.createDocumentFragment();//将html内容存到内存里
while (child = vm.$el.firstChild) {
fragment.appendChild(child);
}
console.log(fragment);
replace(fragment)
function replace(fragment) {
Array.from(fragment.childNodes).forEach(function (node) {
let text = node.textContent.replace(/^\s*|\s*$/g,"");
let reg = /\{\{(.*)\}\}/;
if (node.nodeType === 3 && reg.test(text)) {
// console.log(RegExp.$1)
let arr=RegExp.$1.split('.');
let val=vm;
arr.forEach(function(k){//取this.a.a
val=val[k];
});
node.textContent=text.replace(/\{\{(.*)\}\}/,val);
}
if (node.childNodes.length>0) {
replace(node);
}
});
}
vm.$el.appendChild(fragment);
}
//vm.$options
//观察对象给对象增加ObjectDefineProperty
function Observe(data) {//这里写我们的主要逻辑
for (let key in data) {//把data属性通过object
let val = data[key];
//默认遍历data中劫持所有属性------解决劫持对象多层问题保证所有对象都会被劫持
observer(val);
//.defineproperty的方式 定义属性
Object.defineProperty(data, key, {
enumerable: true,
get() {
return val;
},
set(newval) {
if (newval == val) {//如果设置的值和以前的一样的时候直接返回
return;
}
val = newval;
// 解决新加属性添加到劫持数据里
observer(newval);
}
})
}
}
function observer(data) {
if (typeof data != 'object') return;
return new Observe(data);
}
// 发布订阅
// 绑定的方法 都有update属性
function Dep(){
this.subs=[];
}
Dep.prototype.addSub=function(sub){
this.subs.push(sub);
}
Dep.prototype.notify=function(){
this.subs.forEach(sub=>sub.update());
}
function Watcher(fn){
this.fn=fn;
}
Watcher.prototype.update=function(){
this.fn();
}
// 下面的数据劫持只是当前第一层数据比如: a:1
// 如果a:{a:1}就不行了
// function Jiechi(options={}){
// this.$options=options;//将所有属性挂载到options上
// var data=this._data=this.$options.data;
// observer(data);
// }
// //vm.$options
// //观察对象给对象增加ObjectDefineProperty
// function Observe(data){//这里写我们的主要逻辑
// for(let key in data){//把data属性通过object
// let val=data[key];
// //
// //.defineproperty的方式 定义属性
// Object.defineProperty(data,key,{
// enumerable:true,
// get(){
// return val;
// },
// set(newval){
// if(newval==val){//如果设置的值和以前的一样的时候直接返回
// return;
// }
// val=newval
// }
// })
// }
// }
// function observer(data){
// return new Observe(data);
// }
1.html
<html>
<head>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<p>{{a.a}}</p>
<p>{{a.b}}</p>
</div>
</body>
</html>
<script src="mvvm.js"></script>
<script>
let jiechi=new Jiechi({
el: '#app',
data:{
a:{a:'a',b:'b'}
}
})
console.log(jiechi);
</script>
网友评论