fix(compiler/v-on): handle multiple statements in v-on handler (close #572)
This commit is contained in:
parent
46a793717a
commit
137893a4fd
@ -140,6 +140,22 @@ describe('compiler: transform v-on', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('should handle multiple inline statement', () => {
|
||||
const { node } = parseWithVOn(`<div @click="foo();bar()"/>`)
|
||||
const props = (node.codegenNode as CallExpression)
|
||||
.arguments[1] as ObjectExpression
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: { content: `onClick` },
|
||||
value: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
// should wrap with `{` for multiple statements
|
||||
// in this case the return value is discarded and the behavior is
|
||||
// consistent with 2.x
|
||||
children: [`$event => {`, { content: `foo();bar()` }, `}`]
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('inline statement w/ prefixIdentifiers: true', () => {
|
||||
const { node } = parseWithVOn(`<div @click="foo($event)"/>`, {
|
||||
prefixIdentifiers: true
|
||||
@ -163,6 +179,31 @@ describe('compiler: transform v-on', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('multiple inline statements w/ prefixIdentifiers: true', () => {
|
||||
const { node } = parseWithVOn(`<div @click="foo($event);bar()"/>`, {
|
||||
prefixIdentifiers: true
|
||||
})
|
||||
const props = (node.codegenNode as CallExpression)
|
||||
.arguments[1] as ObjectExpression
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: { content: `onClick` },
|
||||
value: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [
|
||||
`$event => {`,
|
||||
{ content: `_ctx.foo` },
|
||||
`(`,
|
||||
// should NOT prefix $event
|
||||
{ content: `$event` },
|
||||
`);`,
|
||||
{ content: `_ctx.bar` },
|
||||
`()`,
|
||||
`}`
|
||||
]
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('should NOT wrap as function if expression is already function expression', () => {
|
||||
const { node } = parseWithVOn(`<div @click="$event => foo($event)"/>`)
|
||||
const props = (node.codegenNode as CallExpression)
|
||||
|
@ -76,7 +76,9 @@ export function processExpression(
|
||||
context: TransformContext,
|
||||
// some expressions like v-slot props & v-for aliases should be parsed as
|
||||
// function params
|
||||
asParams: boolean = false
|
||||
asParams = false,
|
||||
// v-on handler values may contain multiple statements
|
||||
asRawStatements = false
|
||||
): ExpressionNode {
|
||||
if (!context.prefixIdentifiers || !node.content.trim()) {
|
||||
return node
|
||||
@ -100,9 +102,14 @@ export function processExpression(
|
||||
}
|
||||
|
||||
let ast: any
|
||||
// if the expression is supposed to be used in a function params position
|
||||
// we need to parse it differently.
|
||||
const source = `(${rawExp})${asParams ? `=>{}` : ``}`
|
||||
// exp needs to be parsed differently:
|
||||
// 1. Multiple inline statements (v-on, with presence of `;`): parse as raw
|
||||
// exp, but make sure to pad with spaces for consistent ranges
|
||||
// 2. Expressions: wrap with parens (for e.g. object expressions)
|
||||
// 3. Function arguments (v-for, v-slot): place in a function argument position
|
||||
const source = asRawStatements
|
||||
? ` ${rawExp} `
|
||||
: `(${rawExp})${asParams ? `=>{}` : ``}`
|
||||
try {
|
||||
ast = parseJS(source, { ranges: true })
|
||||
} catch (e) {
|
||||
|
@ -59,11 +59,12 @@ export const transformOn: DirectiveTransform = (
|
||||
if (exp) {
|
||||
const isMemberExp = isMemberExpression(exp.content)
|
||||
const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content))
|
||||
const hasMultipleStatements = exp.content.includes(`;`)
|
||||
|
||||
// process the expression since it's been skipped
|
||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
context.addIdentifiers(`$event`)
|
||||
exp = processExpression(exp, context)
|
||||
exp = processExpression(exp, context, false, hasMultipleStatements)
|
||||
context.removeIdentifiers(`$event`)
|
||||
// with scope analysis, the function is hoistable if it has no reference
|
||||
// to scope variables.
|
||||
@ -85,9 +86,9 @@ export const transformOn: DirectiveTransform = (
|
||||
if (isInlineStatement || (isCacheable && isMemberExp)) {
|
||||
// wrap inline statement in a function expression
|
||||
exp = createCompoundExpression([
|
||||
`$event => (`,
|
||||
`$event => ${hasMultipleStatements ? `{` : `(`}`,
|
||||
...(exp.type === NodeTypes.SIMPLE_EXPRESSION ? [exp] : exp.children),
|
||||
`)`
|
||||
hasMultipleStatements ? `}` : `)`
|
||||
])
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user