|
@@ -1169,6 +1169,8 @@ if (this.user) {
|
|
|
|
|
|
## 异步更新队列
|
|
|
|
|
|
+### 异步更新的意义
|
|
|
+
|
|
|
接下来我们就聊一聊 `Vue` 中的异步更新队列。在上一节中我们讲解了触发依赖的过程,举个例子如下:
|
|
|
|
|
|
```html {2,12}
|
|
@@ -1342,7 +1344,28 @@ export function queueWatcher (watcher: Watcher) {
|
|
|
let waiting = false
|
|
|
```
|
|
|
|
|
|
-为什么需要这个标志呢?我们看 `if` 语句块内的代码就知道了,在 `if` 语句块内先将 `waiting` 的值设置为 `true`,这意味着无论调用多少次 `queueWatcher` 函数,该 `if` 语句块的代码只会执行一次。接着调用 `nextTick` 并以 `flushSchedulerQueue` 函数作为参数,其中 `flushSchedulerQueue` 函数的作用之一就是用来将队列中的观察者统一执行更新的。
|
|
|
+为什么需要这个标志呢?我们看 `if` 语句块内的代码就知道了,在 `if` 语句块内先将 `waiting` 的值设置为 `true`,这意味着无论调用多少次 `queueWatcher` 函数,该 `if` 语句块的代码只会执行一次。接着调用 `nextTick` 并以 `flushSchedulerQueue` 函数作为参数,其中 `flushSchedulerQueue` 函数的作用之一就是用来将队列中的观察者统一执行更新的。对于 `nextTick` 相信大家已经很熟悉了,其实最好理解的方式就是把 `nextTick` 看做 `setTimeout(fn, 0)`,如下:
|
|
|
+
|
|
|
+```js {9}
|
|
|
+export function queueWatcher (watcher: Watcher) {
|
|
|
+ const id = watcher.id
|
|
|
+ if (has[id] == null) {
|
|
|
+ has[id] = true
|
|
|
+ // 省略...
|
|
|
+ // queue the flush
|
|
|
+ if (!waiting) {
|
|
|
+ waiting = true
|
|
|
+ setTimeout(flushSchedulerQueue, 0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+我们完全可以使用 `setTimeout` 替换 `nextTick`,我们只需要执行一次 `setTimeout` 语句即可,`waiting` 变量就保证了 `setTimeout` 语句只会执行一次,这样 `flushSchedulerQueue` 函数将会在下一次事件循环开始时立即调用,但是既然可以使用 `setTimeout` 替换 `nextTick` 那么为什么不用 `setTimeout` 呢?原因就在于 `setTimeout` 并不是最优的选择,`nextTick` 的意义就是它会选择一条最优的解决方案,接下来我们就讨论一下 `nextTick` 是如何实现的。
|
|
|
+
|
|
|
+### nextTick 的实现
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
## 深度观测的实现
|