mirror of https://github.com/vuejs/core.git
feat: support v-on="obj" (#149)
Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
parent
421eba3e01
commit
9412c20531
|
@ -75,3 +75,14 @@ export function render(_ctx) {
|
|||
return n0
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: element transform > v-on="obj" 1`] = `
|
||||
"import { renderEffect as _renderEffect, setDynamicEvents as _setDynamicEvents, template as _template } from 'vue/vapor';
|
||||
const t0 = _template("<div></div>")
|
||||
|
||||
export function render(_ctx) {
|
||||
const n0 = t0()
|
||||
_renderEffect(() => _setDynamicEvents(n0, _ctx.obj))
|
||||
return n0
|
||||
}"
|
||||
`;
|
||||
|
|
|
@ -344,4 +344,32 @@ describe('compiler: element transform', () => {
|
|||
},
|
||||
])
|
||||
})
|
||||
|
||||
test('v-on="obj"', () => {
|
||||
const { code, ir } = compileWithElementTransform(`<div v-on="obj" />`)
|
||||
expect(code).toMatchSnapshot()
|
||||
expect(ir.block.effect).toMatchObject([
|
||||
{
|
||||
expressions: [
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'obj',
|
||||
isStatic: false,
|
||||
},
|
||||
],
|
||||
operations: [
|
||||
{
|
||||
type: IRNodeTypes.SET_DYNAMIC_EVENTS,
|
||||
element: 0,
|
||||
event: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'obj',
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
expect(code).contains('_setDynamicEvents(n0, _ctx.obj)')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { fnExpRE, isMemberExpression } from '@vue/compiler-dom'
|
||||
import type { CodegenContext } from '../generate'
|
||||
import type { SetEventIRNode } from '../ir'
|
||||
import type { SetDynamicEventsIRNode, SetEventIRNode } from '../ir'
|
||||
import { genExpression } from './expression'
|
||||
import {
|
||||
type CodeFragment,
|
||||
|
@ -93,6 +93,21 @@ export function genSetEvent(
|
|||
}
|
||||
}
|
||||
|
||||
export function genSetDynamicEvents(
|
||||
oper: SetDynamicEventsIRNode,
|
||||
context: CodegenContext,
|
||||
): CodeFragment[] {
|
||||
const { vaporHelper } = context
|
||||
return [
|
||||
NEWLINE,
|
||||
...genCall(
|
||||
vaporHelper('setDynamicEvents'),
|
||||
`n${oper.element}`,
|
||||
genExpression(oper.event, context),
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
function genArrayExpression(elements: string[]) {
|
||||
return `[${elements.map(it => JSON.stringify(it)).join(', ')}]`
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { type IREffect, IRNodeTypes, type OperationNode } from '../ir'
|
||||
import type { CodegenContext } from '../generate'
|
||||
import { genInsertNode, genPrependNode } from './dom'
|
||||
import { genSetEvent } from './event'
|
||||
import { genSetDynamicEvents, genSetEvent } from './event'
|
||||
import { genFor } from './for'
|
||||
import { genSetHtml } from './html'
|
||||
import { genIf } from './if'
|
||||
|
@ -38,6 +38,8 @@ export function genOperation(
|
|||
return genSetText(oper, context)
|
||||
case IRNodeTypes.SET_EVENT:
|
||||
return genSetEvent(oper, context)
|
||||
case IRNodeTypes.SET_DYNAMIC_EVENTS:
|
||||
return genSetDynamicEvents(oper, context)
|
||||
case IRNodeTypes.SET_HTML:
|
||||
return genSetHtml(oper, context)
|
||||
case IRNodeTypes.SET_REF:
|
||||
|
|
|
@ -21,6 +21,7 @@ export enum IRNodeTypes {
|
|||
SET_DYNAMIC_PROPS,
|
||||
SET_TEXT,
|
||||
SET_EVENT,
|
||||
SET_DYNAMIC_EVENTS,
|
||||
SET_HTML,
|
||||
SET_REF,
|
||||
SET_MODEL_VALUE,
|
||||
|
@ -94,6 +95,12 @@ export interface SetDynamicPropsIRNode extends BaseIRNode {
|
|||
props: IRProps[]
|
||||
}
|
||||
|
||||
export interface SetDynamicEventsIRNode extends BaseIRNode {
|
||||
type: IRNodeTypes.SET_DYNAMIC_EVENTS
|
||||
element: number
|
||||
event: SimpleExpressionNode
|
||||
}
|
||||
|
||||
export interface SetTextIRNode extends BaseIRNode {
|
||||
type: IRNodeTypes.SET_TEXT
|
||||
element: number
|
||||
|
@ -172,6 +179,7 @@ export type OperationNode =
|
|||
| SetDynamicPropsIRNode
|
||||
| SetTextIRNode
|
||||
| SetEventIRNode
|
||||
| SetDynamicEventsIRNode
|
||||
| SetHtmlIRNode
|
||||
| SetRefIRNode
|
||||
| SetModelValueIRNode
|
||||
|
|
|
@ -14,14 +14,26 @@ const delegatedEvents = /*#__PURE__*/ makeMap(
|
|||
|
||||
export const transformVOn: DirectiveTransform = (dir, node, context) => {
|
||||
let { arg, exp, loc, modifiers } = dir
|
||||
if (!exp && !modifiers.length) {
|
||||
if (!exp && (!modifiers.length || !arg)) {
|
||||
context.options.onError(
|
||||
createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc),
|
||||
)
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
// TODO support v-on="{}"
|
||||
// v-on="obj"
|
||||
if (exp) {
|
||||
context.registerEffect(
|
||||
[exp],
|
||||
[
|
||||
{
|
||||
type: IRNodeTypes.SET_DYNAMIC_EVENTS,
|
||||
element: context.reference(),
|
||||
event: exp,
|
||||
},
|
||||
],
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -122,3 +122,12 @@ const delegatedEventHandler = (e: Event) => {
|
|||
: node.parentNode
|
||||
}
|
||||
}
|
||||
|
||||
export function setDynamicEvents(
|
||||
el: HTMLElement,
|
||||
events: Record<string, (...args: any[]) => any>,
|
||||
) {
|
||||
for (const [event, eventHandler] of Object.entries(events)) {
|
||||
on(el, event, () => eventHandler, { effect: true })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ export {
|
|||
setDynamicProp,
|
||||
setDynamicProps,
|
||||
} from './dom/prop'
|
||||
export { on, delegate, delegateEvents } from './dom/event'
|
||||
export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
|
||||
export { setRef } from './dom/templateRef'
|
||||
|
||||
export { defineComponent } from './apiDefineComponent'
|
||||
|
|
Loading…
Reference in New Issue