]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): fix activated hook when using async component with KeepAlive ...
authoredison <daiwei521@126.com>
Thu, 12 May 2022 00:19:11 +0000 (08:19 +0800)
committerGitHub <noreply@github.com>
Thu, 12 May 2022 00:19:11 +0000 (20:19 -0400)
fix #5095
fix #5651

packages/runtime-core/__tests__/apiAsyncComponent.spec.ts
packages/runtime-core/src/apiAsyncComponent.ts

index b771ba9652de8141409cf0810742395829087cdf..c9ab33ce9179c55d1d42fb2ba2542665af1a1ac0 100644 (file)
@@ -4,9 +4,11 @@ import {
   Component,
   ref,
   nextTick,
-  Suspense
+  Suspense,
+  KeepAlive
 } from '../src'
 import { createApp, nodeOps, serializeInner } from '@vue/runtime-test'
+import { onActivated } from '../src/components/KeepAlive'
 
 const timeout = (n: number = 0) => new Promise(r => setTimeout(r, n))
 
@@ -799,4 +801,38 @@ describe('api: defineAsyncComponent', () => {
     expect(vnodeHooks.onVnodeBeforeUnmount).toHaveBeenCalledTimes(1)
     expect(vnodeHooks.onVnodeUnmounted).toHaveBeenCalledTimes(1)
   })
+
+  test('with keepalive', async () => {
+    const spy = jest.fn()
+    let resolve: (comp: Component) => void
+
+    const Foo = defineAsyncComponent(
+      () =>
+        new Promise(r => {
+          resolve = r as any
+        })
+    )
+
+    const root = nodeOps.createElement('div')
+    const app = createApp({
+      render: () => h(KeepAlive, [h(Foo)])
+    })
+
+    app.mount(root)
+    await nextTick()
+
+    resolve!({
+      setup() {
+        onActivated(() => {
+          spy()
+        })
+        return () => 'resolved'
+      }
+    })
+
+    await timeout()
+    expect(serializeInner(root)).toBe('resolved')
+    expect(spy).toBeCalledTimes(1)
+  })
+
 })
index dc92b90d7224416f792af9df7adc95c906e6832b..957aa0bb5f087f5cb44b990e290e0f419b6436b5 100644 (file)
@@ -6,7 +6,7 @@ import {
   isInSSRComponentSetup,
   ComponentOptions
 } from './component'
-import { isFunction, isObject } from '@vue/shared'
+import { isFunction, isObject, ShapeFlags } from '@vue/shared'
 import { ComponentPublicInstance } from './componentPublicInstance'
 import { createVNode, VNode } from './vnode'
 import { defineComponent } from './apiDefineComponent'
@@ -211,10 +211,14 @@ export function defineAsyncComponent<
 
 function createInnerComp(
   comp: ConcreteComponent,
-  { vnode: { ref, props, children } }: ComponentInternalInstance
+  { vnode: { ref, props, children }, parent }: ComponentInternalInstance
 ) {
   const vnode = createVNode(comp, props, children)
   // ensure inner component inherits the async wrapper's ref owner
   vnode.ref = ref
+  
+  if (parent && isKeepAlive(parent.vnode)) {
+    vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
+  }
   return vnode
 }