Skip to content

Commit a49b6f9

Browse files
Doctor-wusxzz
andauthored
feat(compiler-vapor): support v-on for component (#175)
Co-authored-by: Kevin Deng 三咲智子 <[email protected]>
1 parent bdc4322 commit a49b6f9

File tree

5 files changed

+54
-10
lines changed

5 files changed

+54
-10
lines changed

Diff for: packages/compiler-vapor/__tests__/generators/__snapshots__/component.spec.ts.snap

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`generate component > generate component with emits 1`] = `
4+
"import { toHandlerKey as _toHandlerKey } from 'vue';
5+
import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor';
6+
7+
export function render(_ctx) {
8+
const n0 = _createComponent(_resolveComponent("Comp"), [{
9+
onClick: () => (fn)
10+
}])
11+
const n1 = _createComponent(_resolveComponent("Comp"), [{
12+
[_toHandlerKey(eventName)]: () => (fn)
13+
}])
14+
return [n0, n1]
15+
}"
16+
`;
17+
318
exports[`generate component > generate multi root component 1`] = `
419
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, template as _template } from 'vue/vapor';
520
const t0 = _template("123")

Diff for: packages/compiler-vapor/__tests__/generators/component.spec.ts

+8
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,12 @@ describe('generate component', () => {
2020
const { code } = compile(`<div><Comp/></div>`)
2121
expect(code).toMatchSnapshot()
2222
})
23+
24+
test('generate component with emits', () => {
25+
const { code } = compile(`
26+
<Comp @click="fn" />
27+
<Comp @[eventName]="fn" />
28+
`)
29+
expect(code).toMatchSnapshot()
30+
})
2331
})

Diff for: packages/compiler-vapor/src/generators/prop.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ function genLiteralObjectProps(
8686
}
8787

8888
export function genPropKey(
89-
{ key: node, runtimeCamelize, modifier }: IRProp,
89+
{ key: node, modifier, runtimeCamelize, runtimeHandler }: IRProp,
9090
context: CodegenContext,
9191
): CodeFragment[] {
9292
const { helper } = context
@@ -104,13 +104,14 @@ export function genPropKey(
104104
]
105105
}
106106

107-
const key = genExpression(node, context)
108-
return [
109-
'[',
110-
modifier && `${JSON.stringify(modifier)} + `,
111-
...(runtimeCamelize ? genCall(helper('camelize'), key) : key),
112-
']',
113-
]
107+
let key = genExpression(node, context)
108+
if (runtimeCamelize) {
109+
key = genCall(helper('camelize'), key)
110+
}
111+
if (runtimeHandler) {
112+
key = genCall(helper('toHandlerKey'), key)
113+
}
114+
return ['[', modifier && `${JSON.stringify(modifier)} + `, ...key, ']']
114115
}
115116

116117
function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) {

Diff for: packages/compiler-vapor/src/transform.ts

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export interface DirectiveTransformResult {
4343
value: SimpleExpressionNode
4444
modifier?: '.' | '^'
4545
runtimeCamelize?: boolean
46+
runtimeHandler?: boolean
4647
}
4748

4849
// A structural directive transform is technically also a NodeTransform;

Diff for: packages/compiler-vapor/src/transforms/vOn.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
import { ErrorCodes, createCompilerError } from '@vue/compiler-dom'
1+
import {
2+
ElementTypes,
3+
ErrorCodes,
4+
createCompilerError,
5+
} from '@vue/compiler-dom'
26
import type { DirectiveTransform } from '../transform'
37
import { IRNodeTypes, type KeyOverride, type SetEventIRNode } from '../ir'
48
import { resolveModifiers } from '@vue/compiler-dom'
5-
import { extend, makeMap } from '@vue/shared'
9+
import { extend, makeMap, toHandlerKey } from '@vue/shared'
610
import { resolveExpression } from '../utils'
11+
import { EMPTY_EXPRESSION } from './utils'
712

813
const delegatedEvents = /*#__PURE__*/ makeMap(
914
'beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,' +
@@ -14,6 +19,8 @@ const delegatedEvents = /*#__PURE__*/ makeMap(
1419

1520
export const transformVOn: DirectiveTransform = (dir, node, context) => {
1621
let { arg, exp, loc, modifiers } = dir
22+
const isComponent = node.tagType === ElementTypes.COMPONENT
23+
1724
if (!exp && (!modifiers.length || !arg)) {
1825
context.options.onError(
1926
createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc),
@@ -70,6 +77,18 @@ export const transformVOn: DirectiveTransform = (dir, node, context) => {
7077
}
7178
}
7279

80+
if (isComponent) {
81+
if (arg.isStatic) {
82+
arg = extend({}, arg, { content: toHandlerKey(arg.content) })
83+
}
84+
const handler = exp || EMPTY_EXPRESSION
85+
return {
86+
key: arg,
87+
value: handler,
88+
runtimeHandler: !arg.isStatic,
89+
}
90+
}
91+
7392
const operation: SetEventIRNode = {
7493
type: IRNodeTypes.SET_EVENT,
7594
element: context.reference(),

0 commit comments

Comments
 (0)