refactor: simplify event handler

This commit is contained in:
三咲智子 Kevin Deng 2024-02-07 01:37:07 +08:00
parent ef12b99d0c
commit 38865c7ca1
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
12 changed files with 265 additions and 168 deletions

View File

@ -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)

View File

@ -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)

View File

@ -8,7 +8,7 @@ const t0 = _template("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<a></a><form></form><a></a><div></div><div></div><a></a><div></div><input><input><input><input><input><input><input><input><input><input><input><input><input><input><input>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div>")
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("<div></div><div></div><div></div>")
(() => {
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("<div></div>")
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("<div></div>")
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("<div></div>")
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
}"
`;

View File

@ -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)`)
})
})

View File

@ -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
}
}

View File

@ -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
},
})

View File

@ -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<HTMLSelectElement, any, 'number'> = {
{ 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) =>

View File

@ -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[] = []

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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'