Преглед изворни кода

feat(compiler-vapor): support disabling event delegation (#14924)

edison пре 1 недеља
родитељ
комит
3d6f02faba

+ 6 - 0
packages/compiler-core/src/options.ts

@@ -295,6 +295,12 @@ export interface TransformOptions
    * correctly, e.g. #6938, #7138
    */
   hmr?: boolean
+  /**
+   * Vapor only: control whether eligible static DOM events are compiled to
+   * document-level delegated events.
+   * @default true
+   */
+  eventDelegation?: boolean
 }
 
 export interface CodegenOptions extends SharedTransformCodegenOptions {

+ 2 - 0
packages/compiler-core/src/transform.ts

@@ -155,6 +155,7 @@ export function createTransformContext(
     bindingMetadata = EMPTY_OBJ,
     inline = false,
     isTS = false,
+    eventDelegation = true,
     onError = defaultOnError,
     onWarn = defaultOnWarn,
     compatConfig,
@@ -182,6 +183,7 @@ export function createTransformContext(
     bindingMetadata,
     inline,
     isTS,
+    eventDelegation,
     onError,
     onWarn,
     compatConfig,

+ 14 - 0
packages/compiler-sfc/__tests__/compileTemplate.spec.ts

@@ -555,6 +555,20 @@ test('template-only vapor compile keeps built-in render args for $slots', () =>
   expect(result.code).toContain(`_createIf(() => ($slots.default)`)
 })
 
+test('passes vapor event delegation option to template compiler', () => {
+  const result = compile({
+    filename: 'example.vue',
+    source: `<button @click="onClick" />`,
+    vapor: true,
+    compilerOptions: {
+      eventDelegation: false,
+    },
+  })
+
+  expect(result.code).toContain(`_on(n0, "click", e => _ctx.onClick(e))`)
+  expect(result.code).not.toContain(`_delegateEvents("click")`)
+})
+
 test('returns single-root metadata for root control flow when vapor is enabled', () => {
   const result = compile({
     filename: 'example.vue',

+ 11 - 0
packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap

@@ -260,6 +260,17 @@ export function render(_ctx) {
 }"
 `;
 
+exports[`v-on > should allow disabling event delegation 1`] = `
+"import { on as _on, template as _template } from 'vue';
+const t0 = _template("<div>", 1)
+
+export function render(_ctx) {
+  const n0 = t0()
+  _on(n0, "click", e => _ctx.test(e))
+  return n0
+}"
+`;
+
 exports[`v-on > should delegate event 1`] = `
 "import { createInvoker as _createInvoker, delegateEvents as _delegateEvents, template as _template } from 'vue';
 const t0 = _template("<div>", 1)

+ 17 - 0
packages/compiler-vapor/__tests__/transforms/vOn.spec.ts

@@ -764,6 +764,23 @@ describe('v-on', () => {
     ])
   })
 
+  test('should allow disabling event delegation', () => {
+    const { code, ir, helpers } = compileWithVOn(`<div @click="test"/>`, {
+      eventDelegation: false,
+    })
+
+    expect(code).toMatchSnapshot()
+    expect(helpers).not.contains('delegate')
+    expect(helpers).not.contains('delegateEvents')
+    expect(code).contains('_on(n0, "click", e => _ctx.test(e))')
+    expect(ir.block.operation).toMatchObject([
+      {
+        type: IRNodeTypes.SET_EVENT,
+        delegate: false,
+      },
+    ])
+  })
+
   test('should let runtime event helpers create invokers', () => {
     const { code } = compileWithVOn(
       `<div @click.stop="test" /><div @click.foo="a" @click.bar="b" />`,

+ 1 - 0
packages/compiler-vapor/src/transform.ts

@@ -393,6 +393,7 @@ const defaultOptions = {
   bindingMetadata: EMPTY_OBJ,
   inline: false,
   isTS: false,
+  eventDelegation: true,
   onError: defaultOnError,
   onWarn: defaultOnWarn,
 }

+ 1 - 0
packages/compiler-vapor/src/transforms/vOn.ts

@@ -93,6 +93,7 @@ export const transformVOn: DirectiveTransform = (dir, node, context) => {
   // - no handlers for the same static event on this element that use .stop
   // - is a delegatable event
   const delegate =
+    context.options.eventDelegation &&
     arg.isStatic &&
     !eventOptionModifiers.length &&
     !hasStopHandlerForStaticEvent(node, arg.content) &&