Prechádzať zdrojové kódy

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

fix #5870
Evan You 4 rokov pred
rodič
commit
415091b0ee

+ 15 - 0
packages/compiler-core/__tests__/transforms/transformElement.spec.ts

@@ -1053,6 +1053,21 @@ describe('compiler: element transform', () => {
         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', () => {

+ 10 - 3
packages/compiler-core/src/transforms/transformElement.ts

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

+ 7 - 1
packages/compiler-core/src/transforms/transformSlotOutlet.ts

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

+ 11 - 2
packages/compiler-ssr/src/transforms/ssrTransformComponent.ts

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

+ 2 - 0
packages/compiler-ssr/src/transforms/ssrTransformElement.ts

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