diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 1cde644290b..9ae406e3363 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -81,6 +81,7 @@ export interface FunctionalComponent< props?: ComponentPropsOptions

emits?: E | (keyof E)[] inheritAttrs?: boolean + inheritRef?: boolean displayName?: string } diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 5ee630c4936..206945fc65a 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -100,6 +100,7 @@ export interface ComponentOptionsBase< components?: Record directives?: Record inheritAttrs?: boolean + inheritRef?: boolean emits?: E | EE[] // Internal ------------------------------------------------------------------ diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index a83821b3b38..d63f804f61f 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -172,6 +172,10 @@ export function renderComponentRoot( } root.transition = vnode.transition } + // inherit ref + if (Component.inheritRef && vnode.ref != null) { + root.ref = vnode.ref + } if (__DEV__ && setRoot) { setRoot(root) diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts index 865432ab109..1a92dffefd1 100644 --- a/packages/runtime-core/src/components/BaseTransition.ts +++ b/packages/runtime-core/src/components/BaseTransition.ts @@ -100,6 +100,8 @@ export function useTransitionState(): TransitionState { const BaseTransitionImpl = { name: `BaseTransition`, + inheritRef: true, + props: { mode: String, appear: Boolean, diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index 865cf8d20da..ead43717483 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -63,6 +63,8 @@ const KeepAliveImpl = { // would prevent it from being tree-shaken. __isKeepAlive: true, + inheritRef: true, + props: { include: [String, RegExp, Array], exclude: [String, RegExp, Array], diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index f816459be87..382cd379eed 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -17,7 +17,8 @@ import { ComponentInternalInstance, createComponentInstance, Data, - setupComponent + setupComponent, + Component } from './component' import { renderComponentRoot, @@ -64,6 +65,7 @@ import { import { createHydrationFunctions, RootHydrateFunction } from './hydration' import { invokeDirectiveHook } from './directives' import { startMeasure, endMeasure } from './profiling' +import { ComponentPublicInstance } from './componentProxy' export interface Renderer { render: RootRenderFunction @@ -276,11 +278,21 @@ export const setRef = ( parent: ComponentInternalInstance, vnode: VNode | null ) => { - const value = vnode - ? vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT - ? vnode.component!.proxy - : vnode.el - : null + let value: ComponentPublicInstance | RendererNode | null + if (!vnode) { + value = null + } else { + const { el, component, shapeFlag, type } = vnode + if (shapeFlag & ShapeFlags.COMPONENT && (type as Component).inheritRef) { + return + } + if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) { + value = component!.proxy + } else { + value = el + } + } + const [owner, ref] = rawRef if (__DEV__ && !owner) { warn( diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts index 20e18f832e8..17fbf14ed34 100644 --- a/packages/runtime-dom/src/components/Transition.ts +++ b/packages/runtime-dom/src/components/Transition.ts @@ -37,6 +37,8 @@ export const Transition: FunctionalComponent = ( { slots } ) => h(BaseTransition, resolveTransitionProps(props), slots) +Transition.inheritRef = true + export const TransitionPropsValidators = (Transition.props = { ...(BaseTransition as any).props, name: String,