创建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