Part # HTML

<div id="app">
{{name}}<input id="inputText"  type="text" v-model="name">{{age}}<input id="inputText"  type="text" v-model="age">
</div>
Copy the code

Part # js

var n = 0; function Vue(opt){ this.data = opt.data; Let _id = document.querySelector(opt.el); Observe (this.data,this); // Observe (this.data,this); let _dom = cloneNode(_id,this); _id.appendChild(_dom); Function observe(obj,vm){object.keys (obj). ForEach (key => {defineReactive(vm,key,obj[key])}) Watcher(vm,node,name,nodeType){console.log(' new ') this.vm = vm; this.node = node; this.name = name; this.nodeType = nodeType; Dep.target = this; console.log(Dep.target); } Watcher.prototype = { get:function(){ this.value = this.vm[this.name] }, updata:function(){ this.get() if(this.nodeType == 'input'){ this.node.value = this.value } if(this.nodeType == 'text'){ Prototype = {this.node.nodeValue = this.value}} // constructor function Dep(){this.subs = [] // prototype = {this.node.nodeValue = this.value}} // constructor function Dep(){this.subs = [] // prototype = { notify:function(){ console.log(this.subs); This.subs.foreach (sub =>{sub.updata()})}, addSub:function(sub){console.log(' not executed '); this.subs.push(sub); This.subs = [...new Set(this.subs)] console.log(this.subs); this.subs = [...new Set(this.subs)] console.log(this.subs); }} function defineReactive(obj,key,val){// Subscriber console.log(++n); var x = n; let dep = new Dep(); Object.defineproperty (obj,key,{get:function(){// dep.target The observer instance is mounted to Dep if(dep.target){console.log(" dep.target ") console.log(Dep.target); dep.addSub(Dep.target) } return val }, Set :function(newValue){if(val == newValue){return} val = newValue console.log(' set ${newValue} ') dep.notify(); } }) } function compile(node,vm){ console.log('compile'); console.dir(node.nodeType) var name ='' let reg = /\{\{(.*)\}\}/; let nodeType = 'input' if(node.nodeType == 1){ let attr = node.attributes for(let i = 0,al=attr.length; i<al; i++){ if(attr[i].nodeName == 'v-model'){ nodeType = 'input' name = attr[i].nodeValue; Subs (Dep instance); /* New Watcher (Dep instance); /* New Watcher (Dep instance); */ new watcher (VM,node,name,nodeType) node.adDeventListener ('input',function(){vm[name] = this.value; },false) node.value = vm[name] node.removeAttribute('v-model') } } } if(node.nodeType == 3){ // console.log(node.childNodes[0].nodeValue) if(reg.test(node.nodeValue)){ nodeType = 'text' name = RegExp.$1; new Watcher(vm,node,name,nodeType) node.textContent = vm[name]; } } } function cloneNode(node,vm){ let flag = document.createDocumentFragment() let child while(child = node.firstChild)  { compile(child,vm) flag.appendChild(child) } return flag } var vm = new Vue({ data:{name:'aaa',age:'30'}, El :'#app'}) 1. New Vue, first mount EL, bind data to observer, intercept node node, regenerate node, generate a watcher for each node conforming to {{}} and V-model. Assign this to dep. target, which is the current Watcher instance, and if the node is input and listens for input input, the next step is to get the property, the getter in the Observer, in which case dep. Target is the Watcher instance that was just assigned. Add it to the subs array of the deP for this property, and evaluate it. Each attribute has a DEP collector. The subs of the DEP collector stores the watcher of the attribute. When data is updated, the setter of the Observer will be triggered to call DEP. The updata method of each sub of the SUBs of the DEP is executed and assigned according to the node structureCopy the code