fix(compiler-core): should generate HYDRATE_EVENTS flag on dynamic component that resolves to element

fix #5870
This commit is contained in:
Evan You 2022-05-17 16:39:48 +08:00
parent f811dc2b60
commit 415091b0ee
5 changed files with 45 additions and 6 deletions

View File

@ -1053,6 +1053,21 @@ describe('compiler: element transform', () => {
genFlagText([PatchFlags.PROPS, PatchFlags.HYDRATE_EVENTS]) genFlagText([PatchFlags.PROPS, PatchFlags.HYDRATE_EVENTS])
) )
}) })
// #5870
test('HYDRATE_EVENTS on dynamic component', () => {
const { node } = parseWithElementTransform(
`<component :is="foo" @input="foo" />`,
{
directiveTransforms: {
on: transformOn
}
}
)
expect(node.patchFlag).toBe(
genFlagText([PatchFlags.PROPS, PatchFlags.HYDRATE_EVENTS])
)
})
}) })
describe('dynamic component', () => { describe('dynamic component', () => {

View File

@ -121,7 +121,13 @@ export const transformElement: NodeTransform = (node, context) => {
// props // props
if (props.length > 0) { if (props.length > 0) {
const propsBuildResult = buildProps(node, context) const propsBuildResult = buildProps(
node,
context,
undefined,
isComponent,
isDynamicComponent
)
vnodeProps = propsBuildResult.props vnodeProps = propsBuildResult.props
patchFlag = propsBuildResult.patchFlag patchFlag = propsBuildResult.patchFlag
dynamicPropNames = propsBuildResult.dynamicPropNames dynamicPropNames = propsBuildResult.dynamicPropNames
@ -380,6 +386,8 @@ export function buildProps(
node: ElementNode, node: ElementNode,
context: TransformContext, context: TransformContext,
props: ElementNode['props'] = node.props, props: ElementNode['props'] = node.props,
isComponent: boolean,
isDynamicComponent: boolean,
ssr = false ssr = false
): { ): {
props: PropsExpression | undefined props: PropsExpression | undefined
@ -389,7 +397,6 @@ export function buildProps(
shouldUseBlock: boolean shouldUseBlock: boolean
} { } {
const { tag, loc: elementLoc, children } = node const { tag, loc: elementLoc, children } = node
const isComponent = node.tagType === ElementTypes.COMPONENT
let properties: ObjectExpression['properties'] = [] let properties: ObjectExpression['properties'] = []
const mergeArgs: PropsExpression[] = [] const mergeArgs: PropsExpression[] = []
const runtimeDirectives: DirectiveNode[] = [] const runtimeDirectives: DirectiveNode[] = []
@ -411,8 +418,8 @@ export function buildProps(
const name = key.content const name = key.content
const isEventHandler = isOn(name) const isEventHandler = isOn(name)
if ( if (
!isComponent &&
isEventHandler && isEventHandler &&
(!isComponent || isDynamicComponent) &&
// omit the flag for click handlers because hydration gives click // omit the flag for click handlers because hydration gives click
// dedicated fast path. // dedicated fast path.
name.toLowerCase() !== 'onclick' && name.toLowerCase() !== 'onclick' &&

View File

@ -87,7 +87,13 @@ export function processSlotOutlet(
} }
if (nonNameProps.length > 0) { if (nonNameProps.length > 0) {
const { props, directives } = buildProps(node, context, nonNameProps) const { props, directives } = buildProps(
node,
context,
nonNameProps,
false,
false
)
slotProps = props slotProps = props
if (directives.length) { if (directives.length) {

View File

@ -34,7 +34,8 @@ import {
TRANSITION_GROUP, TRANSITION_GROUP,
CREATE_VNODE, CREATE_VNODE,
CallExpression, CallExpression,
JSChildNode JSChildNode,
RESOLVE_DYNAMIC_COMPONENT
} from '@vue/compiler-dom' } from '@vue/compiler-dom'
import { SSR_RENDER_COMPONENT, SSR_RENDER_VNODE } from '../runtimeHelpers' import { SSR_RENDER_COMPONENT, SSR_RENDER_VNODE } from '../runtimeHelpers'
import { import {
@ -83,6 +84,8 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
} }
const component = resolveComponentType(node, context, true /* ssr */) const component = resolveComponentType(node, context, true /* ssr */)
const isDynamicComponent =
isObject(component) && component.callee === RESOLVE_DYNAMIC_COMPONENT
componentTypeMap.set(node, component) componentTypeMap.set(node, component)
if (isSymbol(component)) { if (isSymbol(component)) {
@ -116,7 +119,13 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
if (node.props.length) { if (node.props.length) {
// note we are not passing ssr: true here because for components, v-on // note we are not passing ssr: true here because for components, v-on
// handlers should still be passed // handlers should still be passed
const { props, directives } = buildProps(node, context) const { props, directives } = buildProps(
node,
context,
undefined,
true,
isDynamicComponent
)
if (props || directives.length) { if (props || directives.length) {
propsExp = buildSSRProps(props, directives, context) propsExp = buildSSRProps(props, directives, context)
} }

View File

@ -89,6 +89,8 @@ export const ssrTransformElement: NodeTransform = (node, context) => {
node, node,
context, context,
node.props, node.props,
false /* isComponent */,
false /* isDynamicComponent */,
true /* ssr */ true /* ssr */
) )
if (props || directives.length) { if (props || directives.length) {