fix(runtime-core): fix activated hook when using async component with KeepAlive (#5459)
fix #5095 fix #5651
This commit is contained in:
		
							parent
							
								
									d4fcfddec6
								
							
						
					
					
						commit
						f1d1cdbb69
					
				@ -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)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user