vue3-yuanma/packages/compiler-core/src/transforms/vOn.ts

89 lines
2.6 KiB
TypeScript
Raw Normal View History

import { DirectiveTransform } from '../transform'
import {
DirectiveNode,
createObjectProperty,
createSimpleExpression,
ExpressionNode,
NodeTypes,
createCompoundExpression,
SimpleExpressionNode
} from '../ast'
import { capitalize } from '@vue/shared'
2019-09-25 10:39:20 +08:00
import { createCompilerError, ErrorCodes } from '../errors'
import { processExpression } from './transformExpression'
import { isMemberExpression } from '../utils'
const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function(?:\s+[\w$]+)?\s*\(/
export interface VOnDirectiveNode extends DirectiveNode {
// v-on without arg is handled directly in ./element.ts due to it affecting
// codegen for the entire props object. This transform here is only for v-on
// *with* args.
arg: ExpressionNode
// exp is guaranteed to be a simple expression here because v-on w/ arg is
// skipped by transformExpression as a special case.
exp: SimpleExpressionNode | undefined
}
export const transformOn: DirectiveTransform = (
dir: VOnDirectiveNode,
node,
context
) => {
const { loc, modifiers, arg } = dir
if (!dir.exp && !modifiers.length) {
2019-09-25 10:39:20 +08:00
context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc))
}
let eventName: ExpressionNode
if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {
if (arg.isStatic) {
eventName = createSimpleExpression(
`on${capitalize(arg.content)}`,
true,
arg.loc
)
} else {
eventName = createCompoundExpression([`"on" + (`, arg, `)`])
}
2019-09-25 10:39:20 +08:00
} else {
2019-10-05 11:12:49 +08:00
// already a compound expression.
eventName = arg
eventName.children.unshift(`"on" + (`)
eventName.children.push(`)`)
2019-09-25 10:39:20 +08:00
}
// TODO .once modifier handling since it is platform agnostic
// other modifiers are handled in compiler-dom
// handler processing
let exp: ExpressionNode | undefined = dir.exp
if (exp) {
const isInlineStatement = !(
isMemberExpression(exp.content) || fnExpRE.test(exp.content)
)
// process the expression since it's been skipped
if (!__BROWSER__ && context.prefixIdentifiers) {
context.addIdentifiers(`$event`)
exp = processExpression(exp, context)
context.removeIdentifiers(`$event`)
}
if (isInlineStatement) {
// wrap inline statement in a function expression
exp = createCompoundExpression([
`$event => (`,
...(exp.type === NodeTypes.SIMPLE_EXPRESSION ? [exp] : exp.children),
`)`
])
}
}
return {
2019-10-11 06:02:51 +08:00
props: [
createObjectProperty(
eventName,
exp || createSimpleExpression(`() => {}`, false, loc)
2019-10-11 06:02:51 +08:00
)
],
needRuntime: false
}
}