Преглед изворни кода

fix: fix scheduler dupe invokes

Evan You пре 7 година
родитељ
комит
75bfa80997

+ 11 - 9
packages/core/src/createRenderer.ts

@@ -160,10 +160,6 @@ export function createRenderer(options: RendererOptions) {
 
   const hooks: Function[] = []
 
-  function queueHook(fn: Function) {
-    hooks.push(fn)
-  }
-
   function flushHooks() {
     let fn
     while ((fn = hooks.shift())) {
@@ -251,7 +247,7 @@ export function createRenderer(options: RendererOptions) {
   }
 
   function mountRef(ref: Ref, el: RenderNode | MountedComponent) {
-    queueHook(() => {
+    hooks.push(() => {
       ref(el)
     })
   }
@@ -1166,8 +1162,9 @@ export function createRenderer(options: RendererOptions) {
         }
       },
       {
-        scheduler: queueUpdate
-        // TODO add API for using onTrigger for component re-render debugging
+        scheduler: queueUpdate,
+        onTrack: instance.renderTracked,
+        onTrigger: instance.renderTriggered
       }
     )
 
@@ -1185,7 +1182,7 @@ export function createRenderer(options: RendererOptions) {
       mountRef(ref, instance)
     }
     if (instance.mounted) {
-      queueHook(() => {
+      hooks.push(() => {
         ;(instance as any).mounted.call(instance.$proxy)
       })
     }
@@ -1220,7 +1217,12 @@ export function createRenderer(options: RendererOptions) {
     }
 
     if (instance.updated) {
-      queueHook(() => {
+      // Because the child's update is executed by the scheduler and not
+      // synchronously within the parent's update call, the child's updated hook
+      // will be added to the queue AFTER the parent's, but they should be
+      // invoked BEFORE the parent's. Therefore we add them to the head of the
+      // queue instead.
+      hooks.unshift(() => {
         ;(instance as any).updated.call(instance.$proxy, nextVNode)
       })
     }

+ 0 - 4
packages/scheduler/__tests__/scheduler.spec.ts

@@ -22,8 +22,6 @@ describe('scheduler', () => {
       calls.push('job1')
       // job1 queues job2
       queueJob(job2)
-      // should be called sync
-      expect(calls).toEqual(['job1', 'job2'])
     }
     const job2 = () => {
       calls.push('job2')
@@ -60,8 +58,6 @@ describe('scheduler', () => {
       calls.push('job1')
       // job1 queues job2
       queueJob(job2, cb2)
-      // should be called sync
-      expect(calls).toEqual(['job1', 'job2'])
     }
     const job2 = () => {
       calls.push('job2')

+ 7 - 11
packages/scheduler/src/index.ts

@@ -2,7 +2,7 @@ const queue: Array<() => void> = []
 const postFlushCbs: Array<() => void> = []
 const p = Promise.resolve()
 
-let flushing = false
+let hasPendingFlush = false
 
 export function nextTick(fn?: () => void): Promise<void> {
   return p.then(fn)
@@ -10,22 +10,18 @@ export function nextTick(fn?: () => void): Promise<void> {
 
 export function queueJob(job: () => void, postFlushCb?: () => void) {
   if (queue.indexOf(job) === -1) {
-    if (flushing) {
-      job()
-    } else {
-      queue.push(job)
+    queue.push(job)
+    if (!hasPendingFlush) {
+      hasPendingFlush = true
+      nextTick(flushJobs)
     }
   }
-  if (postFlushCb) {
+  if (postFlushCb && postFlushCbs.indexOf(postFlushCb) === -1) {
     postFlushCbs.push(postFlushCb)
   }
-  if (!flushing) {
-    nextTick(flushJobs)
-  }
 }
 
 function flushJobs() {
-  flushing = true
   let job
   while ((job = queue.shift())) {
     job()
@@ -33,5 +29,5 @@ function flushJobs() {
   while ((job = postFlushCbs.shift())) {
     job()
   }
-  flushing = false
+  hasPendingFlush = false
 }