feat(compiler): v-on event modifier (#8)

This commit is contained in:
ubugeeei 2023-11-30 06:11:59 +09:00 committed by GitHub
parent 853189c6ac
commit 503615a31e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 3 deletions

View File

@ -71,6 +71,22 @@ export function render() {
" "
`; `;
exports[`compile > directives > v-on > event modifier 1`] = `
"import { template, children, effect, withModifiers, on } from 'vue/vapor';
const t0 = template('<div></div>');
export function render() {
const n0 = t0();
const {
0: [n1],
} = children(n0);
effect(() => {
on(n1, 'click', withModifiers(handleClick, ['prevent', 'stop']));
});
return n0;
}
"
`;
exports[`compile > directives > v-on > simple expression 1`] = ` exports[`compile > directives > v-on > simple expression 1`] = `
"import { template, children, effect, on } from 'vue/vapor'; "import { template, children, effect, on } from 'vue/vapor';
const t0 = template('<div></div>'); const t0 = template('<div></div>');

View File

@ -120,6 +120,18 @@ describe('compile', () => {
}, },
}) })
}) })
test('event modifier', async () => {
const code = await compile(
`<div @click.prevent.stop="handleClick"></div>`,
{
bindingMetadata: {
handleClick: BindingTypes.SETUP_CONST,
},
},
)
expect(code).matchSnapshot()
})
}) })
describe('v-html', () => { describe('v-html', () => {

View File

@ -98,9 +98,14 @@ export function generate(
} }
case IRNodeTypes.SET_EVENT: { case IRNodeTypes.SET_EVENT: {
code = `on(n${oper.element}, ${JSON.stringify(oper.name)}, ${ let value = oper.value
oper.value if (oper.modifiers.length) {
})\n` value = `withModifiers(${value}, ${genArrayExpression(
oper.modifiers,
)})`
vaporHelpers.add('withModifiers')
}
code = `on(n${oper.element}, ${JSON.stringify(oper.name)}, ${value})\n`
vaporHelpers.add('on') vaporHelpers.add('on')
break break
} }
@ -172,3 +177,8 @@ function genChildren(children: DynamicChildren) {
if (!code) return '' if (!code) return ''
return `{${code}}` return `{${code}}`
} }
// TODO: other types (not only string)
function genArrayExpression(elements: string[]) {
return `[${elements.map((it) => `"${it}"`).join(', ')}]`
}

View File

@ -59,6 +59,7 @@ export interface SetEventIRNode extends IRNode {
element: number element: number
name: string name: string
value: string value: string
modifiers: string[]
} }
export interface SetHtmlIRNode extends IRNode { export interface SetHtmlIRNode extends IRNode {

View File

@ -416,6 +416,7 @@ function transformProp(
element: ctx.reference(), element: ctx.reference(),
name: node.arg.content, name: node.arg.content,
value: expr, value: expr,
modifiers,
}) })
break break
} }

View File

@ -39,3 +39,5 @@ export { effect } from './scheduler'
export * from './on' export * from './on'
export * from './render' export * from './render'
export * from './template' export * from './template'
export * from './scheduler'
export { withModifiers } from '@vue/runtime-dom'

View File

@ -0,0 +1,18 @@
<script setup lang="ts">
const handleClick = () => {
console.log('Hello, Vapor!')
}
// @ts-expect-error
globalThis.handleClick = handleClick
</script>
<template>
<form>
<button @click="handleClick">submit</button>
</form>
<form>
<button @click.prevent="handleClick">no submit</button>
</form>
</template>