创建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>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="number">
<button v-click="increment">add</button>
<h3 v-bind="number"></h3>
</div></body>
<script>
class MyVue {
constructor(options) {
this.$options = options;
this.$el = document.querySelector(options.el);
this.$data = options.data;
this.$methods = options.methods;
this._binding = {}; // 依赖收集
this._observe(this.$data); // 观察data数据添加到Watcher中
this._compile(this.$el); // 编译为抽象语法树AST 这里要简单得多
}
_observe(obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
this._binding[key] = {
_directives: []
};
console.log("this._binding[key]", this._binding[key]);
let value = obj[key];
if (typeof value === "object") {
this._observe(value);
}
let binding = this._binding[key];
Object.defineProperty(this.$data, key, {
enumerable: true,
configurable: true,
get() {
console.log(`${key}获取${value}`);
return value;
},
set(newVal) {
console.log(`${key}设置${newVal}`);
if (value !== newVal) {
value = newVal;
binding._directives.forEach(item => item.update());
}
}
});
}
}
}
_compile(root) {
// root为根节点,传入的el
let _this = this;
let nodes = root.children;
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if (node.children.length) {
this._compile(node);
}
if (node.hasAttribute("v-click")) {
node.onclick = (function () {
let attrVal = nodes[i].getAttribute("v-click");
return _this.$methods[attrVal].bind(_this.$data);
})();
}
if (
node.hasAttribute("v-model") &&
(node.tagName === "INPUT" || node.tagName === "TEXTAREA")
) {
node.addEventListener(
"input",
(function (key) {
let attrVal = nodes[i].getAttribute("v-model");
_this._binding[attrVal]._directives.push(
new Watcher("input", node, _this, attrVal, "value")
);
return function () {
_this.$data[attrVal] = nodes[key].value;
};
})(i)
);
}
if (node.hasAttribute("v-bind")) {
let attrVal = nodes[i].getAttribute("v-bind");
_this._binding[attrVal]._directives.push(
new Watcher("text", node, _this, attrVal, "innerHTML")
);
}
}
}
}
class Watcher {
constructor(name, el, vm, exp, attr) {
this.name = name; // 指令名
this.el = el; // 指令对应dom
this.vm = vm; // 指令所属实例
this.exp = exp; // 指令对应值
this.attr = attr; // 绑定属性值
this.update();
}
update() {
this.el[this.attr] = this.vm.$data[this.exp];
}
}
var app = new MyVue({
el: "#app",
data: {
number: 0
},
methods: {
increment() {
this.number++;
}
}
});</script>
</html>
相关推荐
姜海强 2020-08-01
chenjinlong 2020-06-10
conganguo 2020-06-09
88473166 2020-05-14
89427412 2020-05-06
conganguo 2020-05-06
yw00yw 2020-05-04
conganguo 2020-04-25
86523296 2020-04-22
89427412 2020-04-22
yw00yw 2020-04-20
86523296 2020-04-11
檀木雨林 2020-04-11
yw00yw 2020-04-11
yw00yw 2020-04-09
howema 2020-02-21
闲来也无事 2020-02-19
codercheng 2020-02-15
檀木雨林 2020-02-15