Create a VM class to write a simple MVVM model
// index.html <html> <body> <div id="app"> <p>{{name}}</p> <p v-text="age"></p> <div v-html="html"></div> </div> <script SRC ="./vm.js"></script> <script> new vm ({el: "#app", // el only pass selector data: {name: "I am test", age: "17", HTML: "< button > this is a button < / button >"}}) < / script > < / body > < / HTML >Copy the code
Define the mv class
// vm.js class vm {constructor(options) {this.$data = options.data; this.$el = options.el; this.observe(this.$data); new Compiler(this, this.$el); Observe (data) {if(! data || typeof data ! == 'object') { return; } Object.keys(data).forEach(k => { this.defineReactive(data, k, data[k]); $key {object.defineProperty (this, key {get() {return this.$data[key]}, Set (value) {this.$data[key] = value}})} defineReactive(obj, key, value) { this.observe(value); const dep = new Dep(); Object.defineProperty(obj, key, { get() { if(Dep.target ! == null) { dep.addDep(Dep.target) } return value }, set(val) { if(val === value) { return; Class constructor {constructor() {this.deps = []; } addDep(dep) {this.deps.push(dep)} // execute the dependent update method notify() {this.deps.foreach (dep => Constructor (vm, key, cb) {this.$vm = vm; this.$key = key; this.$cb = cb; Dep.target = this; this.$vm[this.$key]; Dep.target = null; } update() { this.$cb && this.$cb(this.$vm[this.$key]) } }Copy the code
The DOM is compiled when the VM is initialized
class Compiler { constructor(vm, el) { this.$vm = vm; if(! el) { return; } const rootDom = document.querySelector(el); const fragment = this.node2fragment(rootDom); this.compile(fragment); Node2fragment (dom) {let child = null; rootdom.appendChild (fragment)} const fragment = document.createDocumentFragment(); while(child = dom.firstChild) { fragment.appendChild(child); } return fragment; } // compile(fragment) {const childNodes = fragment.childnodes; Array.property.forEach.call(childNodes, Node => {if(this.isElement(node)) {else if(this.iselement (node)) this.compileInterpolation(this.$vm, Node.nodetype === 1} // isElement(node) {return node.nodeType === 1} // isElement(node) {return Node. NodeType = = = 3 && / \ {\ {(. *) \} \} /. The test (node. TextContent)} / / compile interpolation compileInterpolation (vm, node) { this.update(node, RegExp.$1, 'text'); } // Update (vm, node, key, dir) {const updateFn = this[' dir 'Updater]; updateFn && updateFn(node, vm[key]); // Update function, New Watcher(vm, key, (val) => {updateFn && updateFn(node, val)})} value) { node.textContent = value; }}Copy the code
Indeed instructions, as well as compilation of events, have time to supplement