]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(vapor): import v-o withModifiers or withKeys on demand (#12539)
authoredison <daiwei521@126.com>
Mon, 16 Dec 2024 06:28:56 +0000 (14:28 +0800)
committerGitHub <noreply@github.com>
Mon, 16 Dec 2024 06:28:56 +0000 (14:28 +0800)
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/vOn.spec.ts
packages/compiler-vapor/src/generators/event.ts
packages/runtime-vapor/src/dom/event.ts

index e5ef3710721ed75bcf59b3dbebfc1800db2753e5..efec7b9ccb70925d57941e591dbefecff847b526 100644 (file)
@@ -304,18 +304,14 @@ export function render(_ctx) {
 `;
 
 exports[`compiler: element transform > props merging: event handlers 1`] = `
-"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
+"import { withKeys as _withKeys, delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 _delegateEvents("click")
 
 export function render(_ctx) {
   const n0 = t0()
-  _delegate(n0, "click", () => _ctx.a, {
-    keys: ["foo"]
-  })
-  _delegate(n0, "click", () => _ctx.b, {
-    keys: ["bar"]
-  })
+  _delegate(n0, "click", () => _withKeys(_ctx.a, ["foo"]))
+  _delegate(n0, "click", () => _withKeys(_ctx.b, ["bar"]))
   return n0
 }"
 `;
index 9a64452d1b09434f781e19f7d2632402e092d0c3..9335d2eb75a38fb295c550808e42c8928f4225a2 100644 (file)
@@ -61,7 +61,7 @@ export function render(_ctx) {
 `;
 
 exports[`v-on > event modifier 1`] = `
-"import { delegate as _delegate, on as _on, delegateEvents as _delegateEvents, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, delegate as _delegate, on as _on, withKeys as _withKeys, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<a></a>")
 const t1 = _template("<form></form>")
 const t2 = _template("<div></div>")
@@ -91,18 +91,10 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
   const n19 = t3()
   const n20 = t3()
   const n21 = t3()
-  _delegate(n0, "click", () => _ctx.handleEvent, {
-    modifiers: ["stop"]
-  })
-  _on(n1, "submit", () => _ctx.handleEvent, {
-    modifiers: ["prevent"]
-  })
-  _delegate(n2, "click", () => _ctx.handleEvent, {
-    modifiers: ["stop", "prevent"]
-  })
-  _delegate(n3, "click", () => _ctx.handleEvent, {
-    modifiers: ["self"]
-  })
+  _delegate(n0, "click", () => _withModifiers(_ctx.handleEvent, ["stop"]))
+  _on(n1, "submit", () => _withModifiers(_ctx.handleEvent, ["prevent"]))
+  _delegate(n2, "click", () => _withModifiers(_ctx.handleEvent, ["stop","prevent"]))
+  _delegate(n3, "click", () => _withModifiers(_ctx.handleEvent, ["self"]))
   _on(n4, "click", () => _ctx.handleEvent, {
     capture: true
   })
@@ -112,53 +104,21 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
   _on(n6, "scroll", () => _ctx.handleEvent, {
     passive: true
   })
-  _delegate(n7, "contextmenu", () => _ctx.handleEvent, {
-    modifiers: ["right"]
-  })
-  _delegate(n8, "click", () => _ctx.handleEvent, {
-    modifiers: ["left"]
-  })
-  _delegate(n9, "mouseup", () => _ctx.handleEvent, {
-    modifiers: ["middle"]
-  })
-  _delegate(n10, "contextmenu", () => _ctx.handleEvent, {
-    modifiers: ["right"], 
-    keys: ["enter"]
-  })
-  _delegate(n11, "keyup", () => _ctx.handleEvent, {
-    keys: ["enter"]
-  })
-  _delegate(n12, "keyup", () => _ctx.handleEvent, {
-    keys: ["tab"]
-  })
-  _delegate(n13, "keyup", () => _ctx.handleEvent, {
-    keys: ["delete"]
-  })
-  _delegate(n14, "keyup", () => _ctx.handleEvent, {
-    keys: ["esc"]
-  })
-  _delegate(n15, "keyup", () => _ctx.handleEvent, {
-    keys: ["space"]
-  })
-  _delegate(n16, "keyup", () => _ctx.handleEvent, {
-    keys: ["up"]
-  })
-  _delegate(n17, "keyup", () => _ctx.handleEvent, {
-    keys: ["down"]
-  })
-  _delegate(n18, "keyup", () => _ctx.handleEvent, {
-    keys: ["left"]
-  })
-  _delegate(n19, "keyup", () => _ctx.submit, {
-    modifiers: ["middle"]
-  })
-  _delegate(n20, "keyup", () => _ctx.submit, {
-    modifiers: ["middle", "self"]
-  })
-  _delegate(n21, "keyup", () => _ctx.handleEvent, {
-    modifiers: ["self"], 
-    keys: ["enter"]
-  })
+  _delegate(n7, "contextmenu", () => _withModifiers(_ctx.handleEvent, ["right"]))
+  _delegate(n8, "click", () => _withModifiers(_ctx.handleEvent, ["left"]))
+  _delegate(n9, "mouseup", () => _withModifiers(_ctx.handleEvent, ["middle"]))
+  _delegate(n10, "contextmenu", () => _withKeys(_withModifiers(_ctx.handleEvent, ["right"]), ["enter"]))
+  _delegate(n11, "keyup", () => _withKeys(_ctx.handleEvent, ["enter"]))
+  _delegate(n12, "keyup", () => _withKeys(_ctx.handleEvent, ["tab"]))
+  _delegate(n13, "keyup", () => _withKeys(_ctx.handleEvent, ["delete"]))
+  _delegate(n14, "keyup", () => _withKeys(_ctx.handleEvent, ["esc"]))
+  _delegate(n15, "keyup", () => _withKeys(_ctx.handleEvent, ["space"]))
+  _delegate(n16, "keyup", () => _withKeys(_ctx.handleEvent, ["up"]))
+  _delegate(n17, "keyup", () => _withKeys(_ctx.handleEvent, ["down"]))
+  _delegate(n18, "keyup", () => _withKeys(_ctx.handleEvent, ["left"]))
+  _delegate(n19, "keyup", () => _withModifiers(_ctx.submit, ["middle"]))
+  _delegate(n20, "keyup", () => _withModifiers(_ctx.submit, ["middle","self"]))
+  _delegate(n21, "keyup", () => _withKeys(_withModifiers(_ctx.handleEvent, ["self"]), ["enter"]))
   return [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19, n20, n21]
 }"
 `;
@@ -315,44 +275,37 @@ export function render(_ctx) {
 `;
 
 exports[`v-on > should not wrap keys guard if no key modifier is present 1`] = `
-"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 _delegateEvents("keyup")
 
 export function render(_ctx) {
   const n0 = t0()
-  _delegate(n0, "keyup", () => _ctx.test, {
-    modifiers: ["exact"]
-  })
+  _delegate(n0, "keyup", () => _withModifiers(_ctx.test, ["exact"]))
   return n0
 }"
 `;
 
 exports[`v-on > should support multiple events and modifiers options w/ prefixIdentifiers: true 1`] = `
-"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, delegate as _delegate, withKeys as _withKeys, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 _delegateEvents("click", "keyup")
 
 export function render(_ctx) {
   const n0 = t0()
-  _delegate(n0, "click", () => _ctx.test, {
-    modifiers: ["stop"]
-  })
-  _delegate(n0, "keyup", () => _ctx.test, {
-    keys: ["enter"]
-  })
+  _delegate(n0, "click", () => _withModifiers(_ctx.test, ["stop"]))
+  _delegate(n0, "keyup", () => _withKeys(_ctx.test, ["enter"]))
   return n0
 }"
 `;
 
 exports[`v-on > should support multiple modifiers and event options w/ prefixIdentifiers: true 1`] = `
-"import { on as _on, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, on as _on, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const n0 = t0()
-  _on(n0, "click", () => _ctx.test, {
-    modifiers: ["stop", "prevent"], 
+  _on(n0, "click", () => _withModifiers(_ctx.test, ["stop","prevent"]), {
     capture: true, 
     once: true
   })
@@ -361,29 +314,26 @@ export function render(_ctx) {
 `;
 
 exports[`v-on > should transform click.middle 1`] = `
-"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 _delegateEvents("mouseup")
 
 export function render(_ctx) {
   const n0 = t0()
-  _delegate(n0, "mouseup", () => _ctx.test, {
-    modifiers: ["middle"]
-  })
+  _delegate(n0, "mouseup", () => _withModifiers(_ctx.test, ["middle"]))
   return n0
 }"
 `;
 
 exports[`v-on > should transform click.middle 2`] = `
-"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, on as _on, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const n0 = t0()
   _renderEffect(() => {
     
-    _on(n0, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _ctx.test, {
-      modifiers: ["middle"], 
+    _on(n0, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _withModifiers(_ctx.test, ["middle"]), {
       effect: true
     })
   })
@@ -392,30 +342,26 @@ export function render(_ctx) {
 `;
 
 exports[`v-on > should transform click.right 1`] = `
-"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 _delegateEvents("contextmenu")
 
 export function render(_ctx) {
   const n0 = t0()
-  _delegate(n0, "contextmenu", () => _ctx.test, {
-    modifiers: ["right"]
-  })
+  _delegate(n0, "contextmenu", () => _withModifiers(_ctx.test, ["right"]))
   return n0
 }"
 `;
 
 exports[`v-on > should transform click.right 2`] = `
-"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, withKeys as _withKeys, on as _on, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const n0 = t0()
   _renderEffect(() => {
     
-    _on(n0, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _ctx.test, {
-      modifiers: ["right"], 
-      keys: ["right"], 
+    _on(n0, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _withKeys(_withModifiers(_ctx.test, ["right"]), ["right"]), {
       effect: true
     })
   })
@@ -436,16 +382,14 @@ export function render(_ctx) {
 `;
 
 exports[`v-on > should wrap both for dynamic key event w/ left/right modifiers 1`] = `
-"import { on as _on, renderEffect as _renderEffect, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, withKeys as _withKeys, on as _on, renderEffect as _renderEffect, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const n0 = t0()
   _renderEffect(() => {
     
-    _on(n0, _ctx.e, () => _ctx.test, {
-      modifiers: ["left"], 
-      keys: ["left"], 
+    _on(n0, _ctx.e, () => _withKeys(_withModifiers(_ctx.test, ["left"]), ["left"]), {
       effect: true
     })
   })
@@ -466,14 +410,12 @@ exports[`v-on > should wrap in unref if identifier is setup-maybe-ref w/ inline:
 `;
 
 exports[`v-on > should wrap keys guard for keyboard events or dynamic events 1`] = `
-"import { on as _on, template as _template } from 'vue';
+"import { withModifiers as _withModifiers, withKeys as _withKeys, on as _on, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 
 export function render(_ctx) {
   const n0 = t0()
-  _on(n0, "keydown", () => _ctx.test, {
-    modifiers: ["stop", "ctrl"], 
-    keys: ["a"], 
+  _on(n0, "keydown", () => _withKeys(_withModifiers(_ctx.test, ["stop","ctrl"]), ["a"]), {
     capture: true
   })
   return n0
@@ -481,15 +423,13 @@ export function render(_ctx) {
 `;
 
 exports[`v-on > should wrap keys guard for static key event w/ left/right modifiers 1`] = `
-"import { delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
+"import { withKeys as _withKeys, delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<div></div>", true)
 _delegateEvents("keyup")
 
 export function render(_ctx) {
   const n0 = t0()
-  _delegate(n0, "keyup", () => _ctx.test, {
-    keys: ["left"]
-  })
+  _delegate(n0, "keyup", () => _withKeys(_ctx.test, ["left"]))
   return n0
 }"
 `;
index 0aac082d653b7290a19f2331f6c55fa44851dc30..2a3f6b48013a4603d5ce0de9b891f22d8d4ce15c 100644 (file)
@@ -428,8 +428,7 @@ describe('v-on', () => {
       },
     ])
     expect(code).contains(
-      `_on(n0, "click", () => _ctx.test, {
-    modifiers: ["stop", "prevent"], 
+      `_on(n0, "click", () => _withModifiers(_ctx.test, ["stop","prevent"]), {
     capture: true, 
     once: true
   })`,
@@ -485,14 +484,9 @@ describe('v-on', () => {
 
     expect(code).matchSnapshot()
     expect(code).contains(
-      `_delegate(n0, "click", () => _ctx.test, {
-    modifiers: ["stop"]
-  })`,
+      `_delegate(n0, "click", () => _withModifiers(_ctx.test, ["stop"]))
+  _delegate(n0, "keyup", () => _withKeys(_ctx.test, ["enter"]))`,
     )
-
-    expect(code).contains(`_delegate(n0, "keyup", () => _ctx.test, {
-    keys: ["enter"]
-  })`)
   })
 
   test('should wrap keys guard for keyboard events or dynamic events', () => {
index 0b3ad5a4d212e26cce154757483a06791c6d6c16..8698c722c7d3fbbb17a1cfb721ad4f4eed147923 100644 (file)
@@ -22,7 +22,7 @@ export function genSetEvent(
   const { element, key, keyOverride, value, modifiers, delegate, effect } = oper
 
   const name = genName()
-  const handler = genEventHandler(context, value)
+  const handler = genEventHandler(context, value, modifiers)
   const eventOptions = genEventOptions()
 
   if (delegate) {
@@ -55,13 +55,11 @@ export function genSetEvent(
   }
 
   function genEventOptions(): CodeFragment[] | undefined {
-    let { options, keys, nonKeys } = modifiers
-    if (!options.length && !nonKeys.length && !keys.length && !effect) return
+    let { options } = modifiers
+    if (!options.length && !effect) return
 
     return genMulti(
       DELIMITERS_OBJECT_NEWLINE,
-      !!nonKeys.length && ['modifiers: ', genArrayExpression(nonKeys)],
-      !!keys.length && ['keys: ', genArrayExpression(keys)],
       effect && ['effect: true'],
       ...options.map((option): CodeFragment[] => [`${option}: true`]),
     )
@@ -83,14 +81,15 @@ export function genSetDynamicEvents(
   ]
 }
 
-function genArrayExpression(elements: string[]) {
-  return `[${elements.map(it => JSON.stringify(it)).join(', ')}]`
-}
-
 export function genEventHandler(
   context: CodegenContext,
   value: SimpleExpressionNode | undefined,
+  modifiers: {
+    nonKeys: string[]
+    keys: string[]
+  } = { nonKeys: [], keys: [] },
 ): CodeFragment[] {
+  let handlerExp: CodeFragment[] = [`() => {}`]
   if (value && value.content.trim()) {
     const isMemberExp = isMemberExpression(value, context.options)
     const isInlineStatement = !(
@@ -102,16 +101,41 @@ export function genEventHandler(
         $event: null,
       })
       const hasMultipleStatements = value.content.includes(`;`)
-      return [
-        '() => $event => ',
+      handlerExp = [
+        '$event => ',
         hasMultipleStatements ? '{' : '(',
         ...expr,
         hasMultipleStatements ? '}' : ')',
       ]
     } else {
-      return ['() => ', ...genExpression(value, context)]
+      handlerExp = [...genExpression(value, context)]
     }
   }
 
-  return ['() => {}']
+  const { keys, nonKeys } = modifiers
+  if (nonKeys.length)
+    handlerExp = genWithModifiers(context, handlerExp, nonKeys)
+  if (keys.length) handlerExp = genWithKeys(context, handlerExp, keys)
+
+  return [`() => `, ...handlerExp]
+}
+
+function genWithModifiers(
+  context: CodegenContext,
+  handler: CodeFragment[],
+  nonKeys: string[],
+): CodeFragment[] {
+  return genCall(
+    context.helper('withModifiers'),
+    handler,
+    JSON.stringify(nonKeys),
+  )
+}
+
+function genWithKeys(
+  context: CodegenContext,
+  handler: CodeFragment[],
+  keys: string[],
+): CodeFragment[] {
+  return genCall(context.helper('withKeys'), handler, JSON.stringify(keys))
 }
index 2f7d6a74c1c318332bdf9900c3ec9a4547d4f944..fbfdb06519dc5ba62b0f7a81392ce60b2041234f 100644 (file)
@@ -8,7 +8,6 @@ import {
   getMetadata,
   recordEventMetadata,
 } from '../componentMetadata'
-import { withKeys, withModifiers } from '@vue/runtime-dom'
 import { queuePostFlushCb } from '@vue/runtime-dom'
 
 export function addEventListener(
@@ -21,19 +20,13 @@ export function addEventListener(
   return (): void => el.removeEventListener(event, handler, options)
 }
 
-interface ModifierOptions {
-  modifiers?: string[]
-  keys?: string[]
-}
-
 export function on(
   el: Element,
   event: string,
   handlerGetter: () => undefined | ((...args: any[]) => any),
-  options: AddEventListenerOptions &
-    ModifierOptions & { effect?: boolean } = {},
+  options: AddEventListenerOptions & { effect?: boolean } = {},
 ): void {
-  const handler: DelegatedHandler = eventHandler(handlerGetter, options)
+  const handler: DelegatedHandler = eventHandler(handlerGetter)
   let cleanupEvent: (() => void) | undefined
   queuePostFlushCb(() => {
     cleanupEvent = addEventListener(el, event, handler, options)
@@ -59,23 +52,17 @@ export function delegate(
   el: HTMLElement,
   event: string,
   handlerGetter: () => undefined | ((...args: any[]) => any),
-  options: ModifierOptions = {},
 ): void {
-  const handler: DelegatedHandler = eventHandler(handlerGetter, options)
+  const handler: DelegatedHandler = eventHandler(handlerGetter)
   handler.delegate = true
   recordEventMetadata(el, event, handler)
 }
 
-function eventHandler(
-  getter: () => undefined | ((...args: any[]) => any),
-  { modifiers, keys }: ModifierOptions = {},
-) {
+function eventHandler(getter: () => undefined | ((...args: any[]) => any)) {
   return (...args: any[]) => {
     let handler = getter()
     if (!handler) return
 
-    if (modifiers) handler = withModifiers(handler, modifiers as any[])
-    if (keys) handler = withKeys(handler, keys)
     handler && handler(...args)
   }
 }