图解
html
1 <body> 2 <script src="./Dvue.js"></script> 3 <script> 4 const app = new DVue({ 5 data: { 6 test: "I am test", 7 foo: { 8 bar: "bar" 9 } 10 } 11 }) 12 13 app.$data.test = "hello world!" 14 // app.$data.foo.bar = "hello!" 15 </script> 16 </body>
Dvue.js
1 class DVue { 2 constructor(options) { 3 this.$options = options 4 5 // 数据响应化 6 this.$data = options.data 7 this.observe(this.$data) 8 9 // 模拟一下watcher创建 10 // 激活get 并将依赖添加到deps数组上 11 new Watcher() 12 this.$data.test 13 new Watcher() 14 this.$data.foo.bar 15 } 16 17 observe(value) { 18 // 判断value是否是对象 19 if (!value || typeof value !== 'object') { 20 return 21 } 22 23 // 遍历该对象 24 Object.keys(value).forEach(key => { 25 this.defineReactive(value, key, value[key]) 26 }) 27 } 28 29 // 数据响应化 30 defineReactive(obj, key, val) { 31 // 判断val内是否还可以继续调用(是否还有对象) 32 this.observe(val) // 递归解决数据嵌套 33 34 // 初始化dep 35 const dep = new Dep() 36 37 Object.defineProperty(obj, key, { 38 get() { 39 // 读取的时候 判断Dep.target是否有,如果有则调用addDep方法将Dep.target添加到deps数组上 40 Dep.target && dep.addDep(Dep.target) 41 return val 42 }, 43 set(newVal) { 44 if (newVal === val) { 45 return; 46 } 47 val = newVal 48 // console.log(`${key}属性更新了:${val}`) 49 dep.notify() // 更新时候调用该方法 50 } 51 }) 52 } 53 } 54 55 56 // Dep: 用来管理Watcher 57 class Dep { 58 constructor() { 59 // 这里存放若干依赖(watcher) |一个watcher对应一个属性 60 this.deps = []; 61 } 62 63 // 添加依赖 64 addDep (dep) { 65 this.deps.push(dep) 66 } 67 68 // 通知方法 69 notify() { 70 this.deps.forEach(dep => dep.update()) 71 } 72 } 73 74 // Watcher 75 class Watcher { 76 constructor () { 77 // 将当前watcher实例指定到Dep静态属性target上 78 Dep.target = this // 当前this就是Watcher对象 79 } 80 81 update() { 82 console.log('属性更新了') 83 } 84 }