1 class MVVM { 2 constructor(options) { 3 this.$options = options; 4 this.$el = options.el; 5 this.$data = options.data; 6 this.observe(this.$data); 7 new Compile(this); 8 } 9 observe(data) { 10 if (!data || typeof data !== 'object') { 11 return; 12 } 13 Object.keys(data).forEach(key => { 14 this.defineReactive(data, key, data[key]); 15 }) 16 } 17 defineReactive(data, key, value) { 18 let dep = new Dep(); 19 Object.defineProperty(data, key, { 20 configurable: false, 21 enumerable: true, 22 get: () => { 23 Dep.target && dep.add(Dep.target); 24 return value; 25 }, 26 set: (newVal) => { 27 if (newVal === value) { return; } 28 value = newVal; 29 dep.notify(); 30 } 31 }) 32 } 33 } 34 class Dep { 35 constructor() { 36 this.deps = []; 37 } 38 add(dep) { 39 this.deps.push(dep); 40 } 41 notify() { 42 this.deps.forEach(dep => { 43 dep.update(); 44 }) 45 } 46 } 47 class Watcher { 48 constructor(vm, cb) { 49 this.vm = vm; 50 this.cb = cb; 51 Dep.target = this; 52 this.vm.$data['word']; 53 Dep.target = null; 54 } 55 update() { 56 this.cb.call(this.vm, this.vm.$data['word']); 57 } 58 } 59 class Compile { 60 constructor(vm) { 61 this.vm = vm; 62 this.changeInputValue(vm); 63 } 64 changeInputValue(vm) { 65 let inputs = document.querySelectorAll('input'); 66 Array.from(inputs).forEach(input => { 67 this.update(input,vm); 68 input.addEventListener('input', (e) => { 69 vm.$data['word'] = e.target.value; 70 }, false) 71 }) 72 } 73 update(input,vm) { 74 input.value = vm.$data['word']; 75 new Watcher(vm, function (value) { 76 input.value = value; 77 }) 78 } 79 }