Vue------发布订阅模式实现

图解

 

 

 

 

 

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 }
posted @ 2020-01-02 14:06  林中有风  阅读(2805)  评论(0编辑  收藏  举报