vue.js
import {Dep} from './dep' import {Compiler} from './compiler' class Observe{ obj:Object; constructor(obj){ this.obj = obj; this.walk(); } walk(){ let keys = Object.keys(this.obj) for(let i = 0; i<keys.length; i++){ defineReactive(this.obj,keys[i],this.obj[keys[i]]) } } } function defineReactive(obj:Object,key:String,val:any) { var dep = new Dep(); Object.defineProperty(obj,key,{ enumerable: true, configurable: true, get:function () { if(Dep.target){ console.log(Dep.target) dep.addSub(Dep.target) } return val }, set:function (newVal) { val = newVal; // childOb = observe(newVal) console.log(8,dep) dep.notify() } }) } export default class Vue{ options:Object; constructor(options){ this.options = options new Observe(this.options.data) let id = this.options.el; let element = document.getElementById(id); let dom = new Compiler(element,this) element.appendChild(dom) } }
dep.js
var uid = 0; export class Dep{ static target: ?Watcher; id:Number; subs:Array; constructor(){ this.id = uid++; this.subs = []; } addSub(sub){ this.subs.push(sub) } notify(){ const subs = this.subs.slice(); for(let i=0;i<subs.length;i++){ console.log('fabu',subs[i]) subs[i].update(); } } }
watcher.js
import {Dep} from './dep' export class Watcher{ vm:Object; node:Object; name:String; type:String; value:any constructor(vm,node,name,type){ Dep.target = this; this.vm = vm; this.node = node; this.name = name; this.type = type; this.update(); } update(){ this.get(); console.log('34444',this.node[this.type]) this.node[this.type] = this.value; } get(){ this.value = this.vm.options.data[this.name]; } }
compiler.js
import {Watcher} from './watcher' export class Compiler{ node:any; vm:Object; constructor(node,vm){ this.node = node; this.vm = vm; this.$frag = this.nodeTofragement(this.node,this.vm) return this.$frag; } compileElemnt(node,vm){ let reg = /\{\{(.*)\}\}/; var vm = this.vm if(node.nodeType == 1){ let attr = node.attributes; for(let i = 0;i<attr.length;i++){ if(attr[i].nodeName == 'v-model'){ let name = attr[i].nodeValue; node.addEventListener('input', e => { vm.options.data[name] = e.target.value; }); console.log('w1') new Watcher(vm,node,name,'value') } } } if(node.nodeType == 3){ if(reg.test(node.nodeValue)){ let name = RegExp.$1; node.nodeValue = vm.options.data[name]; console.log('w2') new Watcher(vm,node,name,'nodeValue') } } } nodeTofragement(node,vm){ let fragment = document.createDocumentFragment(); let child; while(child = node.firstChild){ this.compileElemnt(child,vm); fragment.appendChild(child) } return fragment; } }