mirror of https://github.com/vuejs/core.git
feat(compiler-vapor): support v-on for component (#175)
Co-authored-by: Kevin Deng 三咲智子 <sxzz@sxzz.moe>
This commit is contained in:
parent
bdc43226a0
commit
a49b6f91ca
|
@ -1,5 +1,20 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// 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`] = `
|
exports[`generate component > generate multi root component 1`] = `
|
||||||
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, template as _template } from 'vue/vapor';
|
"import { resolveComponent as _resolveComponent, createComponent as _createComponent, template as _template } from 'vue/vapor';
|
||||||
const t0 = _template("123")
|
const t0 = _template("123")
|
||||||
|
|
|
@ -20,4 +20,12 @@ describe('generate component', () => {
|
||||||
const { code } = compile(`<div><Comp/></div>`)
|
const { code } = compile(`<div><Comp/></div>`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('generate component with emits', () => {
|
||||||
|
const { code } = compile(`
|
||||||
|
<Comp @click="fn" />
|
||||||
|
<Comp @[eventName]="fn" />
|
||||||
|
`)
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -86,7 +86,7 @@ function genLiteralObjectProps(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function genPropKey(
|
export function genPropKey(
|
||||||
{ key: node, runtimeCamelize, modifier }: IRProp,
|
{ key: node, modifier, runtimeCamelize, runtimeHandler }: IRProp,
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
): CodeFragment[] {
|
): CodeFragment[] {
|
||||||
const { helper } = context
|
const { helper } = context
|
||||||
|
@ -104,13 +104,14 @@ export function genPropKey(
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = genExpression(node, context)
|
let key = genExpression(node, context)
|
||||||
return [
|
if (runtimeCamelize) {
|
||||||
'[',
|
key = genCall(helper('camelize'), key)
|
||||||
modifier && `${JSON.stringify(modifier)} + `,
|
}
|
||||||
...(runtimeCamelize ? genCall(helper('camelize'), key) : key),
|
if (runtimeHandler) {
|
||||||
']',
|
key = genCall(helper('toHandlerKey'), key)
|
||||||
]
|
}
|
||||||
|
return ['[', modifier && `${JSON.stringify(modifier)} + `, ...key, ']']
|
||||||
}
|
}
|
||||||
|
|
||||||
function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) {
|
function genPropValue(values: SimpleExpressionNode[], context: CodegenContext) {
|
||||||
|
|
|
@ -43,6 +43,7 @@ export interface DirectiveTransformResult {
|
||||||
value: SimpleExpressionNode
|
value: SimpleExpressionNode
|
||||||
modifier?: '.' | '^'
|
modifier?: '.' | '^'
|
||||||
runtimeCamelize?: boolean
|
runtimeCamelize?: boolean
|
||||||
|
runtimeHandler?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// A structural directive transform is technically also a NodeTransform;
|
// A structural directive transform is technically also a NodeTransform;
|
||||||
|
|
|
@ -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 type { DirectiveTransform } from '../transform'
|
||||||
import { IRNodeTypes, type KeyOverride, type SetEventIRNode } from '../ir'
|
import { IRNodeTypes, type KeyOverride, type SetEventIRNode } from '../ir'
|
||||||
import { resolveModifiers } from '@vue/compiler-dom'
|
import { resolveModifiers } from '@vue/compiler-dom'
|
||||||
import { extend, makeMap } from '@vue/shared'
|
import { extend, makeMap, toHandlerKey } from '@vue/shared'
|
||||||
import { resolveExpression } from '../utils'
|
import { resolveExpression } from '../utils'
|
||||||
|
import { EMPTY_EXPRESSION } from './utils'
|
||||||
|
|
||||||
const delegatedEvents = /*#__PURE__*/ makeMap(
|
const delegatedEvents = /*#__PURE__*/ makeMap(
|
||||||
'beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,' +
|
'beforeinput,click,dblclick,contextmenu,focusin,focusout,input,keydown,' +
|
||||||
|
@ -14,6 +19,8 @@ const delegatedEvents = /*#__PURE__*/ makeMap(
|
||||||
|
|
||||||
export const transformVOn: DirectiveTransform = (dir, node, context) => {
|
export const transformVOn: DirectiveTransform = (dir, node, context) => {
|
||||||
let { arg, exp, loc, modifiers } = dir
|
let { arg, exp, loc, modifiers } = dir
|
||||||
|
const isComponent = node.tagType === ElementTypes.COMPONENT
|
||||||
|
|
||||||
if (!exp && (!modifiers.length || !arg)) {
|
if (!exp && (!modifiers.length || !arg)) {
|
||||||
context.options.onError(
|
context.options.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc),
|
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 = {
|
const operation: SetEventIRNode = {
|
||||||
type: IRNodeTypes.SET_EVENT,
|
type: IRNodeTypes.SET_EVENT,
|
||||||
element: context.reference(),
|
element: context.reference(),
|
||||||
|
|
Loading…
Reference in New Issue