1.后动实现v-model的双向数据绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div> <div class="app"> <input type="text" v-model="inputValue"> {{inputValue}} </div> </div> <script> function observe(data) { if (!data && typeof data !== 'object'){ return; } Object.keys(data).forEach(key => { defineReactive(data, key, data[key]); }) } function defineReactive(data, key, value) { observe(value); var dep = new Dep(); Object.defineProperty(data, key, { get: function(){ console.log(222) if(Dep.target){ dep.addSub(Dep.target) } return value; }, set: function(newVal){ if(value == newVal){ return; } value = newVal; dep.notify(); } }) } function Dep(){ this.subs = []; } Dep.prototype = { addSub(sub){ this.subs.push(sub); }, notify(){ this.subs.forEach(sub =>{ console.log(sub) sub.update(); }) } } //订阅器实现 function Watcher(node, vm ,name){ Dep.target = this; this.vm = vm; this.node = node; = name; this.update(); Dep.target = null; } Watcher.prototype = { update(){ this.get(); if(this.node.nodeType === 3){ this.node.nodeValue = this.value; }else{ this.node.value = this.value; } }, get(){ this.value = this.vm.$data[];//添加订阅器 } } var vm1 = new Vue({ el: ".app", data: { inputValue: 40 } }) function Vue(options){ this.$data = options.data; observe(options.data); var originDom = document.querySelector(options.el); //需要进行编译,解析指令 var fragment = nodeToFragment(originDom, this); document.querySelector(options.el).appendChild(fragment); } function nodeToFragment(node, vm){ var frameEle = document.createDocumentFragment(); var child; while(child = node.childNodes[0]){ compile(child, vm); frameEle.append(child); } return frameEle; } function compile(node, vm){ if (node.nodeType === 1) { //元素节点 for(var i=0; i < node.attributes.length; i++) { if(node.attributes[i].nodeName === 'v-model'){ var name = node.attributes[i].nodeValue; node.value = vm.$data[name]; node.addEventListener('input', function(e){ vm.$data[name] = e.target.value; }) node.removeAttribute('v-model'); } } new Watcher(node, vm, name); } if(node.nodeType === 3){ let reg = /\{\{(.*)\}\}/; // {{xxx}} if(reg.test(node.nodeValue)){ //console.log(node.nodeValue,RegExp.$1) var name = RegExp.$1; node.nodeValue = vm.$data[name]; } new Watcher(node, vm, name); } } setTimeout(()=>{ vm1.$data.inputValue = 80; },2000) </script> </body> </html>