整体流程图

实现简易版本的MVVM框架(Vue)_前端

在10~15分钟完成的自定义Vue

EasyFrame

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>EasyFrame</title>
<script src="./easy-frame.js"></script>
</head>
<body>
<div id="app">
<p>{{count}}</p>
<button @click="add">+1</button>
</div>
<script>
const app = new EasyFrame({
el: "#app",
data: {
count: 0,
},
methods: {
add() {
console.log("add");
this.count++;
},
},
});
</script>
</body>
</html>

observe

function EasyFrame(options) {
this.$options = options;
this.$el = this.$options.el;
this.$data = this.$options.data;
this.$methods = this.$options.methods;
observe(this.$data);
proxy(this);
compile(this.$el, this);
}

compile

function observe(obj) {
function defineReactive(obj, key, val) {
observe(val);
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
// 绑定后清空target,下个对象响应化时,对应绑定
Dep.target && dep.addDep(Dep.target);
console.log("getter");
return val;
},
set(newVal) {
if (newVal != val) {
console.log("setter");
observe(val);
val = newVal;
dep.notify();
}
},
});
}

Object.keys(obj).forEach((key) => defineReactive(obj, key, obj[key]));
}

Watcher&Dep

function Dep() {
this.watchers = [];
this.addDep = function (watcher) {
this.watchers.push(watcher);
};
this.notify = function () {
this.watchers.forEach((watcher) => watcher.update());
};
}

function Watcher(vm, key, fn) {
// 触发依赖收集
Dep.target = this;
vm[key];
Dep.target = null;

// 回调最新val
this.update = function () {
fn && fn(vm[key]);
};
}

proxy

function proxy(vm) {
Object.keys(vm.$data).forEach((key) => {
Object.defineProperty(vm, key, {
get() {
return vm.$data[key];
},
set(val) {
vm.$data[key] = val;
},
});
});
}