feat(compiler-vapor): support v-on for component (#175)

Co-authored-by: Kevin Deng 三咲智子 <sxzz@sxzz.moe>
This commit is contained in:
Doctor Wu 2024-04-15 02:40:59 +08:00 committed by GitHub
parent bdc43226a0
commit a49b6f91ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 54 additions and 10 deletions

View File

@ -1,5 +1,20 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`generate component > generate component with emits 1`] = `
"import { toHandlerKey as _toHandlerKey } from 'vue';
import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
export function render(_ctx) {
const n0 = _createComponent(_resolveComponent("Comp"), [{
onClick: () => (fn)
}])
const n1 = _createComponent(_resolveComponent("Comp"), [{
[_toHandlerKey(eventName)]: () => (fn)
}])
return [n0, n1]
}"
`;
exports[`generate component > generate multi root component 1`] = `
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, template as _template } from 'vue/vapor';
const t0 = _template("123")

View File

@ -20,4 +20,12 @@ describe('generate component', () => {
const { code } = compile(`<div><Comp/></div>`)
expect(code).toMatchSnapshot()
})
test('generate component with emits', () => {
const { code } = compile(`
<Comp @click="fn" />
<Comp @[eventName]="fn" />
`)
expect(code).toMatchSnapshot()
})
})

View File

@ -86,7 +86,7 @@ function genLiteralObjectProps(
}
export function genPropKey(
{ key: node, runtimeCamelize, modifier }: IRProp,
{ key: node, modifier, runtimeCamelize, runtimeHandler }: IRProp,
context: CodegenContext,
): CodeFragment[] {
const { helper } = context
@ -104,13 +104,14 @@ export function genPropKey(
]
}
const key = genExpression(node, context)
return [
'[',
modifier && `${JSON.stringify(modifier)} + `,
...(runtimeCamelize ? genCall(helper('camelize'), key) : key),
']',
]
let key = genExpression(node, context)
if (runtimeCamelize) {
key = genCall(helper('camelize'), key)
}
if (runtimeHandler) {
key = genCall(helper('toHandlerKey'), key)
}
return ['[', modifier && `${JSON.stringify(modifier)} + `, ...key, ']']
}
function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) {

View File

@ -43,6 +43,7 @@ export interface DirectiveTransformResult {
value: SimpleExpressionNode
modifier?: '.' | '^'
runtimeCamelize?: boolean
runtimeHandler?: boolean
}
// A structural directive transform is technically also a NodeTransform;

View File

@ -1,9 +1,14 @@
import { ErrorCodes, createCompilerError } from '@vue/compiler-dom'
import {
ElementTypes,
ErrorCodes,
createCompilerError,
} from '@vue/compiler-dom'
import type { DirectiveTransform } from '../transform'
import { IRNodeTypes, type KeyOverride, type SetEventIRNode } from '../ir'
import { resolveModifiers } from '@vue/compiler-dom'
import { extend, makeMap } from '@vue/shared'
import { extend, makeMap, toHandlerKey } from '@vue/shared'
import { resolveExpression } from '../utils'
import { EMPTY_EXPRESSION } from './utils'
const delegatedEvents = /*#__PURE__*/ makeMap(
'beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,' +
@ -14,6 +19,8 @@ const delegatedEvents = /*#__PURE__*/ makeMap(
export const transformVOn: DirectiveTransform = (dir, node, context) => {
let { arg, exp, loc, modifiers } = dir
const isComponent = node.tagType === ElementTypes.COMPONENT
if (!exp && (!modifiers.length || !arg)) {
context.options.onError(
createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc),
@ -70,6 +77,18 @@ export const transformVOn: DirectiveTransform = (dir, node, context) => {
}
}
if (isComponent) {
if (arg.isStatic) {
arg = extend({}, arg, { content: toHandlerKey(arg.content) })
}
const handler = exp || EMPTY_EXPRESSION
return {
key: arg,
value: handler,
runtimeHandler: !arg.isStatic,
}
}
const operation: SetEventIRNode = {
type: IRNodeTypes.SET_EVENT,
element: context.reference(),