Просмотр исходного кода

fix: fix async component resolving in sibling mounted hook

fix #7107
Evan You 8 лет назад
Родитель
Сommit
dd21eacc33

+ 4 - 1
src/core/instance/lifecycle.js

@@ -193,7 +193,10 @@ export function mountComponent (
     }
   }
 
-  vm._watcher = new Watcher(vm, updateComponent, noop)
+  // we set this to vm._watcher inside the wathcer's constructor
+  // since the watcher's initial patch may call $forceUpdate (e.g. inside child
+  // component's mounted hook), which relies on vm._watcher being already defined
+  new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)
   hydrating = false
 
   // manually mounted instance, call mounted on self

+ 5 - 1
src/core/observer/watcher.js

@@ -44,9 +44,13 @@ export default class Watcher {
     vm: Component,
     expOrFn: string | Function,
     cb: Function,
-    options?: Object
+    options?: ?Object,
+    isRenderWatcher?: boolean
   ) {
     this.vm = vm
+    if (isRenderWatcher) {
+      vm._watcher = this
+    }
     vm._watchers.push(this)
     // options
     if (options) {

+ 29 - 0
test/unit/features/component/component-async.spec.js

@@ -342,5 +342,34 @@ describe('Component async', () => {
         done()
       }, 50)
     })
+
+    // #7107
+    it(`should work when resolving sync in sibling component's mounted hook`, done => {
+      let resolveTwo
+
+      const vm = new Vue({
+        template: `<div><one/> <two/></div>`,
+        components: {
+          one: {
+            template: `<div>one</div>`,
+            mounted () {
+              resolveTwo()
+            }
+          },
+          two: resolve => {
+            resolveTwo = () => {
+              resolve({
+                template: `<div>two</div>`
+              })
+            }
+          }
+        }
+      }).$mount()
+
+      expect(vm.$el.textContent).toBe('one ')
+      waitForUpdate(() => {
+        expect(vm.$el.textContent).toBe('one two')
+      }).then(done)
+    })
   })
 })