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,
 | 
					  Component,
 | 
				
			||||||
  ref,
 | 
					  ref,
 | 
				
			||||||
  nextTick,
 | 
					  nextTick,
 | 
				
			||||||
  Suspense
 | 
					  Suspense,
 | 
				
			||||||
 | 
					  KeepAlive
 | 
				
			||||||
} from '../src'
 | 
					} from '../src'
 | 
				
			||||||
import { createApp, nodeOps, serializeInner } from '@vue/runtime-test'
 | 
					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))
 | 
					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.onVnodeBeforeUnmount).toHaveBeenCalledTimes(1)
 | 
				
			||||||
    expect(vnodeHooks.onVnodeUnmounted).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,
 | 
					  isInSSRComponentSetup,
 | 
				
			||||||
  ComponentOptions
 | 
					  ComponentOptions
 | 
				
			||||||
} from './component'
 | 
					} from './component'
 | 
				
			||||||
import { isFunction, isObject } from '@vue/shared'
 | 
					import { isFunction, isObject, ShapeFlags } from '@vue/shared'
 | 
				
			||||||
import { ComponentPublicInstance } from './componentPublicInstance'
 | 
					import { ComponentPublicInstance } from './componentPublicInstance'
 | 
				
			||||||
import { createVNode, VNode } from './vnode'
 | 
					import { createVNode, VNode } from './vnode'
 | 
				
			||||||
import { defineComponent } from './apiDefineComponent'
 | 
					import { defineComponent } from './apiDefineComponent'
 | 
				
			||||||
@ -211,10 +211,14 @@ export function defineAsyncComponent<
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function createInnerComp(
 | 
					function createInnerComp(
 | 
				
			||||||
  comp: ConcreteComponent,
 | 
					  comp: ConcreteComponent,
 | 
				
			||||||
  { vnode: { ref, props, children } }: ComponentInternalInstance
 | 
					  { vnode: { ref, props, children }, parent }: ComponentInternalInstance
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
  const vnode = createVNode(comp, props, children)
 | 
					  const vnode = createVNode(comp, props, children)
 | 
				
			||||||
  // ensure inner component inherits the async wrapper's ref owner
 | 
					  // ensure inner component inherits the async wrapper's ref owner
 | 
				
			||||||
  vnode.ref = ref
 | 
					  vnode.ref = ref
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  if (parent && isKeepAlive(parent.vnode)) {
 | 
				
			||||||
 | 
					    vnode.shapeFlag |= ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  return vnode
 | 
					  return vnode
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user