diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap index a3c0fb71d..e40340193 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap @@ -203,7 +203,7 @@ export function render(_ctx) { _prepend(n4, n1) _insert(n2, n4, n5) _append(n4, n3) - _on(n4, "click", (...args) => (_ctx.handleClick && _ctx.handleClick(...args))) + _on(n4, "click", () => _ctx.handleClick) _renderEffect(() => { _setText(n1, _ctx.count) _setText(n2, _ctx.count) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap index 0ea33a106..1a1e1a94a 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap @@ -11,7 +11,7 @@ export function render(_ctx) { const n1 = _createFor(() => (_ctx.items), (_block) => { const n2 = t0() const { 0: [n3],} = _children(n2) - _on(n3, "click", $event => (_ctx.remove(_block.s[0]))) + _on(n3, "click", () => $event => (_ctx.remove(_block.s[0]))) _renderEffect(() => { const [item] = _block.s _setText(n3, item) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap index 97a156204..e4ccc3e55 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap @@ -8,7 +8,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "fooBar", (...args) => (_ctx.onMount && _ctx.onMount(...args))) + _on(n1, "fooBar", () => _ctx.onMount) return n0 }" `; @@ -21,7 +21,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", (...args) => (_ctx.a['b' + _ctx.c] && _ctx.a['b' + _ctx.c](...args))) + _on(n1, "click", () => _ctx.a['b' + _ctx.c]) return n0 }" `; @@ -34,7 +34,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _renderEffect(() => _on(n1, _ctx.event, (...args) => (_ctx.handler && _ctx.handler(...args)))) + _renderEffect(() => _on(n1, _ctx.event, () => _ctx.handler)) return n0 }" `; @@ -47,7 +47,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _renderEffect(() => _on(n1, _ctx.event(_ctx.foo), (...args) => (_ctx.handler && _ctx.handler(...args)))) + _renderEffect(() => _on(n1, _ctx.event(_ctx.foo), () => _ctx.handler)) return n0 }" `; @@ -60,41 +60,80 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _renderEffect(() => _on(n1, _ctx.event, (...args) => (_ctx.handler && _ctx.handler(...args)))) + _renderEffect(() => _on(n1, _ctx.event, () => _ctx.handler)) return n0 }" `; exports[`v-on > event modifier 1`] = ` -"import { template as _template, children as _children, withModifiers as _withModifiers, on as _on, withKeys as _withKeys } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1], 1: [n2], 2: [n3], 3: [n4], 4: [n5], 5: [n6], 6: [n7], 7: [n8], 8: [n9], 9: [n10], 10: [n11], 11: [n12], 12: [n13], 13: [n14], 14: [n15], 15: [n16], 16: [n17], 17: [n18], 18: [n19], 19: [n20], 20: [n21], 21: [n22],} = _children(n0) - _on(n1, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["stop"])) - _on(n2, "submit", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["prevent"])) - _on(n3, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["stop", "prevent"])) - _on(n4, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["self"])) - _on(n5, "click", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { capture: true }) - _on(n6, "click", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { once: true }) - _on(n7, "scroll", (...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), { passive: true }) - _on(n8, "contextmenu", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["right"])) - _on(n9, "click", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["left"])) - _on(n10, "mouseup", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["middle"])) - _on(n11, "contextmenu", _withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["right"])) - _on(n12, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["enter"])) - _on(n13, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["tab"])) - _on(n14, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["delete"])) - _on(n15, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["esc"])) - _on(n16, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["space"])) - _on(n17, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["up"])) - _on(n18, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["down"])) - _on(n19, "keyup", _withKeys((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["left"])) - _on(n20, "keyup", _withModifiers((...args) => (_ctx.submit && _ctx.submit(...args)), ["middle"])) - _on(n21, "keyup", _withModifiers((...args) => (_ctx.submit && _ctx.submit(...args)), ["middle", "self"])) - _on(n22, "keyup", _withKeys(_withModifiers((...args) => (_ctx.handleEvent && _ctx.handleEvent(...args)), ["self"]), ["enter"])) + _on(n1, "click", () => _ctx.handleEvent, undefined, { + modifiers: ["stop"] + }) + _on(n2, "submit", () => _ctx.handleEvent, undefined, { + modifiers: ["prevent"] + }) + _on(n3, "click", () => _ctx.handleEvent, undefined, { + modifiers: ["stop", "prevent"] + }) + _on(n4, "click", () => _ctx.handleEvent, undefined, { + modifiers: ["self"] + }) + _on(n5, "click", () => _ctx.handleEvent, { capture: true }) + _on(n6, "click", () => _ctx.handleEvent, { once: true }) + _on(n7, "scroll", () => _ctx.handleEvent, { passive: true }) + _on(n8, "contextmenu", () => _ctx.handleEvent, undefined, { + modifiers: ["right"] + }) + _on(n9, "click", () => _ctx.handleEvent, undefined, { + modifiers: ["left"] + }) + _on(n10, "mouseup", () => _ctx.handleEvent, undefined, { + modifiers: ["middle"] + }) + _on(n11, "contextmenu", () => _ctx.handleEvent, undefined, { + modifiers: ["right"] + }) + _on(n12, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["enter"] + }) + _on(n13, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["tab"] + }) + _on(n14, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["delete"] + }) + _on(n15, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["esc"] + }) + _on(n16, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["space"] + }) + _on(n17, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["up"] + }) + _on(n18, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["down"] + }) + _on(n19, "keyup", () => _ctx.handleEvent, undefined, { + keys: ["left"] + }) + _on(n20, "keyup", () => _ctx.submit, undefined, { + modifiers: ["middle"] + }) + _on(n21, "keyup", () => _ctx.submit, undefined, { + modifiers: ["middle", "self"] + }) + _on(n22, "keyup", () => _ctx.handleEvent, undefined, { + modifiers: ["self"], + keys: ["enter"] + }) return n0 }" `; @@ -107,7 +146,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", e => _ctx.foo(e)) + _on(n1, "click", () => e => _ctx.foo(e)) return n0 }" `; @@ -120,7 +159,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", $event => (_ctx.foo($event))) + _on(n1, "click", () => $event => (_ctx.foo($event))) return n0 }" `; @@ -133,7 +172,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", $event => {_ctx.foo($event);_ctx.bar()}) + _on(n1, "click", () => $event => {_ctx.foo($event);_ctx.bar()}) return n0 }" `; @@ -146,7 +185,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", $event => {_ctx.i++;_ctx.foo($event)}) + _on(n1, "click", () => $event => {_ctx.i++;_ctx.foo($event)}) return n0 }" `; @@ -159,7 +198,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", (e: any): any => _ctx.foo(e)) + _on(n1, "click", () => (e: any): any => _ctx.foo(e)) return n0 }" `; @@ -172,7 +211,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", + _on(n1, "click", () => $event => { _ctx.foo($event) } @@ -189,7 +228,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", $event => _ctx.foo($event)) + _on(n1, "click", () => $event => _ctx.foo($event)) return n0 }" `; @@ -202,7 +241,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", (...args) => (_ctx.a['b' + _ctx.c] && _ctx.a['b' + _ctx.c](...args))) + _on(n1, "click", () => _ctx.a['b' + _ctx.c]) return n0 }" `; @@ -215,7 +254,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", $event => { + _on(n1, "click", () => $event => { _ctx.foo(); _ctx.bar() }) @@ -231,7 +270,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", $event => {_ctx.foo();_ctx.bar()}) + _on(n1, "click", () => $event => {_ctx.foo();_ctx.bar()}) return n0 }" `; @@ -244,99 +283,118 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", (...args) => (_ctx.foo.bar && _ctx.foo.bar(...args))) + _on(n1, "click", () => _ctx.foo.bar) return n0 }" `; exports[`v-on > should not wrap keys guard if no key modifier is present 1`] = ` -"import { template as _template, children as _children, withModifiers as _withModifiers, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "keyup", _withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["exact"])) + _on(n1, "keyup", () => _ctx.test, undefined, { + modifiers: ["exact"] + }) return n0 }" `; exports[`v-on > should support multiple events and modifiers options w/ prefixIdentifiers: true 1`] = ` -"import { template as _template, children as _children, withModifiers as _withModifiers, on as _on, withKeys as _withKeys } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", _withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["stop"])) - _on(n1, "keyup", _withKeys((...args) => (_ctx.test && _ctx.test(...args)), ["enter"])) + _on(n1, "click", () => _ctx.test, undefined, { + modifiers: ["stop"] + }) + _on(n1, "keyup", () => _ctx.test, undefined, { + keys: ["enter"] + }) return n0 }" `; exports[`v-on > should support multiple modifiers and event options w/ prefixIdentifiers: true 1`] = ` -"import { template as _template, children as _children, withModifiers as _withModifiers, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", _withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["stop", "prevent"]), { capture: true, once: true }) + _on(n1, "click", () => _ctx.test, { capture: true, once: true }, { + modifiers: ["stop", "prevent"] + }) return n0 }" `; exports[`v-on > should transform click.middle 1`] = ` -"import { template as _template, children as _children, withModifiers as _withModifiers, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "mouseup", _withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["middle"])) + _on(n1, "mouseup", () => _ctx.test, undefined, { + modifiers: ["middle"] + }) return n0 }" `; exports[`v-on > should transform click.middle 2`] = ` -"import { template as _template, children as _children, renderEffect as _renderEffect, withModifiers as _withModifiers, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, renderEffect as _renderEffect, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _renderEffect(() => _on(n1, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), _withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["middle"]))) + _renderEffect(() => { + _on(n1, (_ctx.event) === "click" ? "mouseup" : (_ctx.event), () => _ctx.test, undefined, { + modifiers: ["middle"] + })}) return n0 }" `; exports[`v-on > should transform click.right 1`] = ` -"import { template as _template, children as _children, withModifiers as _withModifiers, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "contextmenu", _withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["right"])) + _on(n1, "contextmenu", () => _ctx.test, undefined, { + modifiers: ["right"] + }) return n0 }" `; exports[`v-on > should transform click.right 2`] = ` -"import { template as _template, children as _children, renderEffect as _renderEffect, withModifiers as _withModifiers, withKeys as _withKeys, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, renderEffect as _renderEffect, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _renderEffect(() => _on(n1, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), _withKeys(_withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["right"]), ["right"]))) + _renderEffect(() => { + _on(n1, (_ctx.event) === "click" ? "contextmenu" : (_ctx.event), () => _ctx.test, undefined, { + modifiers: ["right"], + keys: ["right"] + })}) return n0 }" `; @@ -349,20 +407,24 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", $event => (_ctx.i++)) + _on(n1, "click", () => $event => (_ctx.i++)) return n0 }" `; exports[`v-on > should wrap both for dynamic key event w/ left/right modifiers 1`] = ` -"import { template as _template, children as _children, renderEffect as _renderEffect, withModifiers as _withModifiers, withKeys as _withKeys, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, renderEffect as _renderEffect, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _renderEffect(() => _on(n1, _ctx.e, _withKeys(_withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["left"]), ["left"]))) + _renderEffect(() => { + _on(n1, _ctx.e, () => _ctx.test, undefined, { + modifiers: ["left"], + keys: ["left"] + })}) return n0 }" `; @@ -373,35 +435,40 @@ const t0 = _template("
") (() => { const n0 = t0() const { 0: [n1], 1: [n2], 2: [n3],} = _children(n0) - _on(n1, "click", $event => (x.value=_unref(y))) - _on(n2, "click", $event => (x.value++)) - _on(n3, "click", $event => ({ x: x.value } = _unref(y))) + _on(n1, "click", () => $event => (x.value=_unref(y))) + _on(n2, "click", () => $event => (x.value++)) + _on(n3, "click", () => $event => ({ x: x.value } = _unref(y))) return n0 })()" `; exports[`v-on > should wrap keys guard for keyboard events or dynamic events 1`] = ` -"import { template as _template, children as _children, withModifiers as _withModifiers, withKeys as _withKeys, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "keydown", _withKeys(_withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["stop", "ctrl"]), ["a"]), { capture: true }) + _on(n1, "keydown", () => _ctx.test, { capture: true }, { + modifiers: ["stop", "ctrl"], + keys: ["a"] + }) return n0 }" `; exports[`v-on > should wrap keys guard for static key event w/ left/right modifiers 1`] = ` -"import { template as _template, children as _children, withKeys as _withKeys, on as _on } from 'vue/vapor'; +"import { template as _template, children as _children, on as _on } from 'vue/vapor'; const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "keyup", _withKeys((...args) => (_ctx.test && _ctx.test(...args)), ["left"])) + _on(n1, "keyup", () => _ctx.test, undefined, { + keys: ["left"] + }) return n0 }" `; @@ -414,7 +481,7 @@ const t0 = _template("
") export function render(_ctx) { const n0 = t0() const { 0: [n1],} = _children(n0) - _on(n1, "click", (...args) => (_ctx.handleClick && _ctx.handleClick(...args))) + _on(n1, "click", () => _ctx.handleClick) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts index f316301a8..1377ab197 100644 --- a/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vOn.spec.ts @@ -167,7 +167,7 @@ describe('v-on', () => { ]) expect(code).matchSnapshot() - expect(code).contains('_on(n1, "click", $event => (_ctx.i++))') + expect(code).contains('_on(n1, "click", () => $event => (_ctx.i++))') }) test('should wrap in unref if identifier is setup-maybe-ref w/ inline: true', () => { @@ -186,10 +186,12 @@ describe('v-on', () => { expect(vaporHelpers).contains('unref') expect(helpers.size).toBe(0) - expect(code).contains('_on(n1, "click", $event => (x.value=_unref(y)))') - expect(code).contains('_on(n2, "click", $event => (x.value++))') expect(code).contains( - '_on(n3, "click", $event => ({ x: x.value } = _unref(y)))', + '_on(n1, "click", () => $event => (x.value=_unref(y)))', + ) + expect(code).contains('_on(n2, "click", () => $event => (x.value++))') + expect(code).contains( + '_on(n3, "click", () => $event => ({ x: x.value } = _unref(y)))', ) }) @@ -207,7 +209,9 @@ describe('v-on', () => { // should wrap with `{` for multiple statements // in this case the return value is discarded and the behavior is // consistent with 2.x - expect(code).contains('_on(n1, "click", $event => {_ctx.foo();_ctx.bar()})') + expect(code).contains( + '_on(n1, "click", () => $event => {_ctx.foo();_ctx.bar()})', + ) }) test('should handle multi-line statement', () => { @@ -225,7 +229,7 @@ describe('v-on', () => { // in this case the return value is discarded and the behavior is // consistent with 2.x expect(code).contains( - '_on(n1, "click", $event => {\n_ctx.foo();\n_ctx.bar()\n})', + '_on(n1, "click", () => $event => {\n_ctx.foo();\n_ctx.bar()\n})', ) }) @@ -243,7 +247,9 @@ describe('v-on', () => { expect(code).matchSnapshot() // should NOT prefix $event - expect(code).contains('_on(n1, "click", $event => (_ctx.foo($event)))') + expect(code).contains( + '_on(n1, "click", () => $event => (_ctx.foo($event)))', + ) }) test('multiple inline statements w/ prefixIdentifiers: true', () => { @@ -261,7 +267,7 @@ describe('v-on', () => { expect(code).matchSnapshot() // should NOT prefix $event expect(code).contains( - '_on(n1, "click", $event => {_ctx.foo($event);_ctx.bar()})', + '_on(n1, "click", () => $event => {_ctx.foo($event);_ctx.bar()})', ) }) @@ -276,7 +282,7 @@ describe('v-on', () => { ]) expect(code).matchSnapshot() - expect(code).contains('_on(n1, "click", $event => _ctx.foo($event))') + expect(code).contains('_on(n1, "click", () => $event => _ctx.foo($event))') }) test('should NOT wrap as function if expression is already function expression (with Typescript)', () => { @@ -293,7 +299,9 @@ describe('v-on', () => { ]) expect(code).matchSnapshot() - expect(code).contains('_on(n1, "click", (e: any): any => _ctx.foo(e))') + expect(code).contains( + '_on(n1, "click", () => (e: any): any => _ctx.foo(e))', + ) }) test('should NOT wrap as function if expression is already function expression (with newlines)', () => { @@ -359,9 +367,7 @@ describe('v-on', () => { ]) expect(code).matchSnapshot() - expect(code).contains( - `_on(n1, "click", (...args) => (_ctx.a['b' + _ctx.c] && _ctx.a['b' + _ctx.c](...args)))`, - ) + expect(code).contains(`_on(n1, "click", () => _ctx.a['b' + _ctx.c])`) }) test('function expression w/ prefixIdentifiers: true', () => { @@ -377,7 +383,7 @@ describe('v-on', () => { ]) expect(code).matchSnapshot() - expect(code).contains('_on(n1, "click", e => _ctx.foo(e))') + expect(code).contains('_on(n1, "click", () => e => _ctx.foo(e))') }) test('should error if no expression AND no modifier', () => { @@ -463,8 +469,6 @@ describe('v-on', () => { ) expect(vaporHelpers).contains('on') - expect(vaporHelpers).contains('withModifiers') - expect(ir.operation).toMatchObject([ { type: IRNodeTypes.SET_EVENT, @@ -483,8 +487,7 @@ describe('v-on', () => { ]) expect(code).matchSnapshot() - expect(code).contains('_withModifiers') - expect(code).contains('["stop", "prevent"]') + expect(code).contains('modifiers: ["stop", "prevent"]') expect(code).contains('{ capture: true, once: true }') }) @@ -536,12 +539,11 @@ describe('v-on', () => { ]) expect(code).matchSnapshot() - expect(code).contains( - '_on(n1, "click", _withModifiers((...args) => (_ctx.test && _ctx.test(...args)), ["stop"]))', - ) - expect(code).contains( - '_on(n1, "keyup", _withKeys((...args) => (_ctx.test && _ctx.test(...args)), ["enter"]))', - ) + expect(code).contains(`_on(n1, "click", () => _ctx.test, undefined`) + expect(code).contains(`modifiers: ["stop"]`) + + expect(code).contains(`_on(n1, "keyup", () => _ctx.test, undefined`) + expect(code).contains(`keys: ["enter"]`) }) test('should wrap keys guard for keyboard events or dynamic events', () => { @@ -723,8 +725,6 @@ describe('v-on', () => { }) expect(code).matchSnapshot() - expect(code).contains( - `_on(n1, "click", (...args) => (_ctx.foo.bar && _ctx.foo.bar(...args)))`, - ) + expect(code).contains(`_on(n1, "click", () => _ctx.foo.bar)`) }) }) diff --git a/packages/compiler-vapor/src/generators/event.ts b/packages/compiler-vapor/src/generators/event.ts index 77a68433e..1033397e1 100644 --- a/packages/compiler-vapor/src/generators/event.ts +++ b/packages/compiler-vapor/src/generators/event.ts @@ -1,5 +1,12 @@ import { isMemberExpression } from '@vue/compiler-dom' -import { type CodeFragment, type CodegenContext, NEWLINE } from '../generate' +import { + type CodeFragment, + type CodegenContext, + INDENT_END, + INDENT_START, + NEWLINE, + buildCodeFragment, +} from '../generate' import type { SetEventIRNode } from '../ir' import { genExpression } from './expression' @@ -15,13 +22,24 @@ export function genSetEvent( const { keys, nonKeys, options } = oper.modifiers const name = genName() - const handler = genFinalizedHandler() - const opt = - !!options.length && `{ ${options.map(v => `${v}: true`).join(', ')} }` + const handler = genEventHandler() + const modifierOptions = genModifierOptions() + const handlerOptions = options.length + ? `{ ${options.map(v => `${v}: true`).join(', ')} }` + : modifierOptions + ? 'undefined' + : undefined return [ NEWLINE, - ...call(vaporHelper('on'), `n${oper.element}`, name, handler, opt), + ...call( + vaporHelper('on'), + `n${oper.element}`, + name, + handler, + handlerOptions, + modifierOptions, + ), ] function genName(): CodeFragment[] { @@ -42,55 +60,41 @@ export function genSetEvent( if (exp && exp.content.trim()) { const isMemberExp = isMemberExpression(exp.content, ctxOptions) const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content)) - const hasMultipleStatements = exp.content.includes(`;`) if (isInlineStatement) { const expr = context.withId(() => genExpression(exp, context), { $event: null, }) + const hasMultipleStatements = exp.content.includes(`;`) return [ - '$event => ', + '() => $event => ', hasMultipleStatements ? '{' : '(', ...expr, hasMultipleStatements ? '}' : ')', ] } else { - const expr = genExpression(exp, context) - if (isMemberExp) { - return ['(...args) => (', ...expr, ' && ', ...expr, '(...args))'] - } else { - return expr - } + return ['() => ', ...genExpression(exp, context)] } } - return '() => {}' + + return ['() => {}'] } - function genFinalizedHandler() { - let expr = genEventHandler() - + function genModifierOptions() { + const hasOptions = nonKeys.length || keys.length + if (!hasOptions) return + const [frag, push] = buildCodeFragment('{', INDENT_START) if (nonKeys.length) { - expr = [ - vaporHelper('withModifiers'), - '(', - ...expr, - ', ', - genArrayExpression(nonKeys), - ')', - ] + push(NEWLINE, 'modifiers: ', genArrayExpression(nonKeys)) + } + if (keys.length && nonKeys.length) { + push(',') } if (keys.length) { - expr = [ - vaporHelper('withKeys'), - '(', - ...expr, - ', ', - genArrayExpression(keys), - ')', - ] + push(NEWLINE, 'keys: ', genArrayExpression(keys)) } - - return expr + push(INDENT_END, NEWLINE, '}') + return frag } } diff --git a/packages/runtime-vapor/__tests__/vShow.spec.ts b/packages/runtime-vapor/__tests__/vShow.spec.ts index 142e57519..42c5351da 100644 --- a/packages/runtime-vapor/__tests__/vShow.spec.ts +++ b/packages/runtime-vapor/__tests__/vShow.spec.ts @@ -29,7 +29,7 @@ const createDemo = (defaultValue: boolean) => 1: [n2], } = children(n0) withDirectives(n2, [[vShow, () => visible.value]]) - on(n1 as HTMLElement, 'click', handleClick) + on(n1 as HTMLElement, 'click', () => handleClick) return n0 }, }) diff --git a/packages/runtime-vapor/src/directives/vModel.ts b/packages/runtime-vapor/src/directives/vModel.ts index cff5ffbcd..0df7946c7 100644 --- a/packages/runtime-vapor/src/directives/vModel.ts +++ b/packages/runtime-vapor/src/directives/vModel.ts @@ -8,7 +8,7 @@ import { } from '@vue/shared' import type { ComponentInternalInstance } from '../component' import type { ObjectDirective } from '../directive' -import { on } from '../dom/on' +import { addEventListener } from '../dom/event' import { nextTick } from '../scheduler' import { warn } from '../warning' @@ -50,7 +50,7 @@ export const vModelText: ObjectDirective< assignFnMap.set(el, assigner) const castToNumber = number // || (vnode.props && vnode.props.type === 'number') - on(el, lazy ? 'change' : 'input', e => { + addEventListener(el, lazy ? 'change' : 'input', e => { if ((e.target as any).composing) return let domValue: string | number = el.value if (trim) { @@ -62,18 +62,18 @@ export const vModelText: ObjectDirective< assigner(domValue) }) if (trim) { - on(el, 'change', () => { + addEventListener(el, 'change', () => { el.value = el.value.trim() }) } if (!lazy) { - on(el, 'compositionstart', onCompositionStart) - on(el, 'compositionend', onCompositionEnd) + addEventListener(el, 'compositionstart', onCompositionStart) + addEventListener(el, 'compositionend', onCompositionEnd) // Safari < 10.2 & UIWebView doesn't fire compositionend when // switching focus before confirming composition choice // this also fixes the issue where some browsers e.g. iOS Chrome // fires "change" instead of "input" on autocomplete. - on(el, 'change', onCompositionEnd) + addEventListener(el, 'change', onCompositionEnd) } }, // set value on mounted so it's after min/max for type="range" @@ -122,7 +122,7 @@ export const vModelSelect: ObjectDirective = { { value, oldValue, instance, modifiers: { number = false } = {} }, ) { const isSetModel = isSet(value) - on(el, 'change', () => { + addEventListener(el, 'change', () => { const selectedVal = Array.prototype.filter .call(el.options, (o: HTMLOptionElement) => o.selected) .map((o: HTMLOptionElement) => diff --git a/packages/runtime-vapor/src/dom.ts b/packages/runtime-vapor/src/dom.ts index e8fe75b3c..f87cbeb37 100644 --- a/packages/runtime-vapor/src/dom.ts +++ b/packages/runtime-vapor/src/dom.ts @@ -1,9 +1,9 @@ import { isArray, toDisplayString } from '@vue/shared' import type { Block, ParentBlock } from './render' -export * from './dom/patchProp' +export * from './dom/prop' +export * from './dom/event' export * from './dom/templateRef' -export * from './dom/on' export function normalizeBlock(block: Block): Node[] { const nodes: Node[] = [] diff --git a/packages/runtime-vapor/src/dom/event.ts b/packages/runtime-vapor/src/dom/event.ts new file mode 100644 index 000000000..e8d018025 --- /dev/null +++ b/packages/runtime-vapor/src/dom/event.ts @@ -0,0 +1,55 @@ +import { + getCurrentEffect, + getCurrentScope, + onEffectCleanup, + onScopeDispose, +} from '@vue/reactivity' +import { recordPropMetadata } from './prop' +import { toHandlerKey } from '@vue/shared' +import { withKeys, withModifiers } from '@vue/runtime-dom' + +export function addEventListener( + el: HTMLElement, + event: string, + handler: (...args: any) => any, + options?: AddEventListenerOptions, +) { + el.addEventListener(event, handler, options) + return () => el.removeEventListener(event, handler, options) +} + +export function on( + el: HTMLElement, + event: string, + handlerGetter: () => undefined | ((...args: any[]) => any), + options?: AddEventListenerOptions, + { modifiers, keys }: { modifiers?: string[]; keys?: string[] } = {}, +) { + recordPropMetadata(el, toHandlerKey(event), handlerGetter) + const cleanup = addEventListener( + el, + event, + (...args: any[]) => { + let handler = handlerGetter() + if (!handler) return + + if (modifiers) { + handler = withModifiers(handler, modifiers) + } + if (keys) { + handler = withKeys(handler, keys) + } + handler && handler(...args) + }, + options, + ) + + const scope = getCurrentScope() + const effect = getCurrentEffect() + + if (effect && effect.scope === scope) { + onEffectCleanup(cleanup) + } else if (scope) { + onScopeDispose(cleanup) + } +} diff --git a/packages/runtime-vapor/src/dom/on.ts b/packages/runtime-vapor/src/dom/on.ts deleted file mode 100644 index f0d729165..000000000 --- a/packages/runtime-vapor/src/dom/on.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { - getCurrentEffect, - getCurrentScope, - onEffectCleanup, - onScopeDispose, -} from '@vue/reactivity' -import { recordPropMetadata } from './patchProp' -import { toHandlerKey } from '@vue/shared' - -export function on( - el: HTMLElement, - event: string, - handler: (...args: any) => any, - options?: AddEventListenerOptions, -) { - recordPropMetadata(el, toHandlerKey(event), handler) - el.addEventListener(event, handler, options) - - const scope = getCurrentScope() - const effect = getCurrentEffect() - - const cleanup = () => el.removeEventListener(event, handler, options) - if (effect && effect.scope === scope) { - onEffectCleanup(cleanup) - } else if (scope) { - onScopeDispose(cleanup) - } -} diff --git a/packages/runtime-vapor/src/dom/patchProp.ts b/packages/runtime-vapor/src/dom/prop.ts similarity index 100% rename from packages/runtime-vapor/src/dom/patchProp.ts rename to packages/runtime-vapor/src/dom/prop.ts diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts index 3e3fb53e9..35348f60f 100644 --- a/packages/runtime-vapor/src/index.ts +++ b/packages/runtime-vapor/src/index.ts @@ -37,7 +37,6 @@ export { getCurrentScope, onScopeDispose, } from '@vue/reactivity' -export { withModifiers, withKeys } from '@vue/runtime-dom' export { nextTick } from './scheduler' export { getCurrentInstance, type ComponentInternalInstance } from './component'