Explorar o código

fix(runtime-core): pass component instance to flushPreFlushCbs on unmount (#14221)

close #14215
linzhe hai 4 meses
pai
achega
e857e12c0a

+ 40 - 0
packages/runtime-core/__tests__/apiCreateApp.spec.ts

@@ -645,6 +645,46 @@ describe('api: createApp', () => {
     expect(order).toMatchObject(['render', 'render', 'post watcher'])
   })
 
+  // #14215
+  test("unmount new app should not trigger other app's watcher", async () => {
+    const compWatcherTriggerFn = vi.fn()
+    const data = ref(true)
+    const foo = ref('')
+
+    const createNewApp = () => {
+      const app = createApp({ render: () => h('new app') })
+      const wrapper = nodeOps.createElement('div')
+      app.mount(wrapper)
+      return function destroy() {
+        app.unmount()
+      }
+    }
+
+    const Comp = defineComponent({
+      setup() {
+        watch(() => foo.value, compWatcherTriggerFn)
+        return () => h('div', 'comp')
+      },
+    })
+
+    const App = defineComponent({
+      setup() {
+        return () => (data.value ? h(Comp) : null)
+      },
+    })
+
+    createApp(App).mount(nodeOps.createElement('div'))
+    await nextTick()
+
+    data.value = false
+    const destroy = createNewApp()
+    foo.value = 'bar'
+    destroy()
+    await nextTick()
+
+    expect(compWatcherTriggerFn).toBeCalledTimes(0)
+  })
+
   // config.compilerOptions is tested in packages/vue since it is only
   // supported in the full build.
 })

+ 3 - 1
packages/runtime-core/src/renderer.ts

@@ -2394,9 +2394,11 @@ function baseCreateRenderer(
 
   let isFlushing = false
   const render: RootRenderFunction = (vnode, container, namespace) => {
+    let instance
     if (vnode == null) {
       if (container._vnode) {
         unmount(container._vnode, null, null, true)
+        instance = container._vnode.component
       }
     } else {
       patch(
@@ -2412,7 +2414,7 @@ function baseCreateRenderer(
     container._vnode = vnode
     if (!isFlushing) {
       isFlushing = true
-      flushPreFlushCbs()
+      flushPreFlushCbs(instance)
       flushPostFlushCbs()
       isFlushing = false
     }