Skip to content

Commit 9412c20

Browse files
Jevon617sxzz
andauthored
feat: support v-on="obj" (#149)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
1 parent 421eba3 commit 9412c20

File tree

8 files changed

+90
-5
lines changed

8 files changed

+90
-5
lines changed

packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,14 @@ export function render(_ctx) {
7575
return n0
7676
}"
7777
`;
78+
79+
exports[`compiler: element transform > v-on="obj" 1`] = `
80+
"import { renderEffect as _renderEffect, setDynamicEvents as _setDynamicEvents, template as _template } from 'vue/vapor';
81+
const t0 = _template("<div></div>")
82+
83+
export function render(_ctx) {
84+
const n0 = t0()
85+
_renderEffect(() => _setDynamicEvents(n0, _ctx.obj))
86+
return n0
87+
}"
88+
`;

packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,4 +344,32 @@ describe('compiler: element transform', () => {
344344
},
345345
])
346346
})
347+
348+
test('v-on="obj"', () => {
349+
const { code, ir } = compileWithElementTransform(`<div v-on="obj" />`)
350+
expect(code).toMatchSnapshot()
351+
expect(ir.block.effect).toMatchObject([
352+
{
353+
expressions: [
354+
{
355+
type: NodeTypes.SIMPLE_EXPRESSION,
356+
content: 'obj',
357+
isStatic: false,
358+
},
359+
],
360+
operations: [
361+
{
362+
type: IRNodeTypes.SET_DYNAMIC_EVENTS,
363+
element: 0,
364+
event: {
365+
type: NodeTypes.SIMPLE_EXPRESSION,
366+
content: 'obj',
367+
isStatic: false,
368+
},
369+
},
370+
],
371+
},
372+
])
373+
expect(code).contains('_setDynamicEvents(n0, _ctx.obj)')
374+
})
347375
})

packages/compiler-vapor/src/generators/event.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { fnExpRE, isMemberExpression } from '@vue/compiler-dom'
22
import type { CodegenContext } from '../generate'
3-
import type { SetEventIRNode } from '../ir'
3+
import type { SetDynamicEventsIRNode, SetEventIRNode } from '../ir'
44
import { genExpression } from './expression'
55
import {
66
type CodeFragment,
@@ -93,6 +93,21 @@ export function genSetEvent(
9393
}
9494
}
9595

96+
export function genSetDynamicEvents(
97+
oper: SetDynamicEventsIRNode,
98+
context: CodegenContext,
99+
): CodeFragment[] {
100+
const { vaporHelper } = context
101+
return [
102+
NEWLINE,
103+
...genCall(
104+
vaporHelper('setDynamicEvents'),
105+
`n${oper.element}`,
106+
genExpression(oper.event, context),
107+
),
108+
]
109+
}
110+
96111
function genArrayExpression(elements: string[]) {
97112
return `[${elements.map(it => JSON.stringify(it)).join(', ')}]`
98113
}

packages/compiler-vapor/src/generators/operation.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { type IREffect, IRNodeTypes, type OperationNode } from '../ir'
22
import type { CodegenContext } from '../generate'
33
import { genInsertNode, genPrependNode } from './dom'
4-
import { genSetEvent } from './event'
4+
import { genSetDynamicEvents, genSetEvent } from './event'
55
import { genFor } from './for'
66
import { genSetHtml } from './html'
77
import { genIf } from './if'
@@ -38,6 +38,8 @@ export function genOperation(
3838
return genSetText(oper, context)
3939
case IRNodeTypes.SET_EVENT:
4040
return genSetEvent(oper, context)
41+
case IRNodeTypes.SET_DYNAMIC_EVENTS:
42+
return genSetDynamicEvents(oper, context)
4143
case IRNodeTypes.SET_HTML:
4244
return genSetHtml(oper, context)
4345
case IRNodeTypes.SET_REF:

packages/compiler-vapor/src/ir.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export enum IRNodeTypes {
2121
SET_DYNAMIC_PROPS,
2222
SET_TEXT,
2323
SET_EVENT,
24+
SET_DYNAMIC_EVENTS,
2425
SET_HTML,
2526
SET_REF,
2627
SET_MODEL_VALUE,
@@ -94,6 +95,12 @@ export interface SetDynamicPropsIRNode extends BaseIRNode {
9495
props: IRProps[]
9596
}
9697

98+
export interface SetDynamicEventsIRNode extends BaseIRNode {
99+
type: IRNodeTypes.SET_DYNAMIC_EVENTS
100+
element: number
101+
event: SimpleExpressionNode
102+
}
103+
97104
export interface SetTextIRNode extends BaseIRNode {
98105
type: IRNodeTypes.SET_TEXT
99106
element: number
@@ -172,6 +179,7 @@ export type OperationNode =
172179
| SetDynamicPropsIRNode
173180
| SetTextIRNode
174181
| SetEventIRNode
182+
| SetDynamicEventsIRNode
175183
| SetHtmlIRNode
176184
| SetRefIRNode
177185
| SetModelValueIRNode

packages/compiler-vapor/src/transforms/vOn.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,26 @@ const delegatedEvents = /*#__PURE__*/ makeMap(
1414

1515
export const transformVOn: DirectiveTransform = (dir, node, context) => {
1616
let { arg, exp, loc, modifiers } = dir
17-
if (!exp && !modifiers.length) {
17+
if (!exp && (!modifiers.length || !arg)) {
1818
context.options.onError(
1919
createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc),
2020
)
2121
}
2222

2323
if (!arg) {
24-
// TODO support v-on="{}"
24+
// v-on="obj"
25+
if (exp) {
26+
context.registerEffect(
27+
[exp],
28+
[
29+
{
30+
type: IRNodeTypes.SET_DYNAMIC_EVENTS,
31+
element: context.reference(),
32+
event: exp,
33+
},
34+
],
35+
)
36+
}
2537
return
2638
}
2739

packages/runtime-vapor/src/dom/event.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,12 @@ const delegatedEventHandler = (e: Event) => {
122122
: node.parentNode
123123
}
124124
}
125+
126+
export function setDynamicEvents(
127+
el: HTMLElement,
128+
events: Record<string, (...args: any[]) => any>,
129+
) {
130+
for (const [event, eventHandler] of Object.entries(events)) {
131+
on(el, event, () => eventHandler, { effect: true })
132+
}
133+
}

packages/runtime-vapor/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export {
8484
setDynamicProp,
8585
setDynamicProps,
8686
} from './dom/prop'
87-
export { on, delegate, delegateEvents } from './dom/event'
87+
export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
8888
export { setRef } from './dom/templateRef'
8989

9090
export { defineComponent } from './apiDefineComponent'

0 commit comments

Comments
 (0)