Explorar el Código

perf(v-on): constant handlers with modifiers should not be treated as dynamic

Evan You hace 2 años
padre
commit
4d94ebfe75

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

@@ -1160,6 +1160,20 @@ describe('compiler: element transform', () => {
         genFlagText([PatchFlags.PROPS, PatchFlags.NEED_HYDRATION])
       )
     })
+
+    test('should not have PROPS patchflag for constant v-on handlers', () => {
+      const { node } = parseWithElementTransform(`<div @keydown="foo" />`, {
+        prefixIdentifiers: true,
+        bindingMetadata: {
+          foo: BindingTypes.SETUP_CONST
+        },
+        directiveTransforms: {
+          on: transformOn
+        }
+      })
+      // should only have hydration flag
+      expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION))
+    })
   })
 
   describe('dynamic component', () => {

+ 8 - 1
packages/compiler-core/src/transforms/transformElement.ts

@@ -19,7 +19,8 @@ import {
   TemplateTextChildNode,
   DirectiveArguments,
   createVNodeCall,
-  ConstantTypes
+  ConstantTypes,
+  JSChildNode
 } from '../ast'
 import {
   PatchFlags,
@@ -459,6 +460,12 @@ export function buildProps(
         hasVnodeHook = true
       }
 
+      if (isEventHandler && value.type === NodeTypes.JS_CALL_EXPRESSION) {
+        // handler wrapped with internal helper e.g. withModifiers(fn)
+        // extract the actual expression
+        value = value.arguments[0] as JSChildNode
+      }
+
       if (
         value.type === NodeTypes.JS_CACHE_EXPRESSION ||
         ((value.type === NodeTypes.SIMPLE_EXPRESSION ||

+ 19 - 5
packages/compiler-dom/__tests__/transforms/vOn.spec.ts

@@ -7,7 +7,8 @@ import {
   NodeTypes,
   ObjectExpression,
   transform,
-  VNodeCall
+  VNodeCall,
+  BindingTypes
 } from '@vue/compiler-core'
 import { transformOn } from '../../src/transforms/vOn'
 import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers'
@@ -25,12 +26,11 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) {
     },
     ...options
   })
+  const node = (ast.children[0] as ElementNode).codegenNode as VNodeCall
   return {
     root: ast,
-    props: (
-      ((ast.children[0] as ElementNode).codegenNode as VNodeCall)
-        .props as ObjectExpression
-    ).properties
+    node,
+    props: (node.props as ObjectExpression).properties
   }
 }
 
@@ -288,4 +288,18 @@ describe('compiler-dom: transform v-on', () => {
       }
     })
   })
+
+  test('should not have PROPS patchFlag for constant v-on handlers with modifiers', () => {
+    const { node } = parseWithVOn(`<div @keydown.up="foo" />`, {
+      prefixIdentifiers: true,
+      bindingMetadata: {
+        foo: BindingTypes.SETUP_CONST
+      },
+      directiveTransforms: {
+        on: transformOn
+      }
+    })
+    // should only have hydration flag
+    expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION))
+  })
 })