Skip to content

Commit 9551d0b

Browse files
committed
feat: support multiple in v-on
1 parent 38ed488 commit 9551d0b

File tree

3 files changed

+35
-38
lines changed

3 files changed

+35
-38
lines changed

src/core/common.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { CallExpression, ConditionalExpression, Expression, LogicalExpression, Node } from '@babel/types'
1+
import type { ArrowFunctionExpression, CallExpression, ConditionalExpression, Expression, FunctionExpression, LogicalExpression, Node } from '@babel/types'
22
import type { MagicString } from '@vue-macros/common'
33

44
export function addAttribute(
@@ -88,3 +88,8 @@ export function isLogicalExpression(node: Node): node is LogicalExpression {
8888
return node.type === 'LogicalExpression'
8989
&& isJSXExpression(node.right)
9090
}
91+
92+
export function isFunctionExpression(node: Node): node is FunctionExpression | ArrowFunctionExpression {
93+
return node.type === 'FunctionExpression'
94+
|| node.type === 'ArrowFunctionExpression'
95+
}

src/core/transform.ts

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { Node } from '@babel/types'
99
import type { Options } from '../types'
1010
import { transformVIf } from './v-if'
1111
import { transformVFor } from './v-for'
12-
import { isConditionalExpression, isJSXElement, isJSXExpression, isLogicalExpression, isMapCallExpression } from './common'
12+
import { isConditionalExpression, isFunctionExpression, isJSXElement, isJSXExpression, isLogicalExpression, isMapCallExpression } from './common'
1313

1414
export type RootNodes = {
1515
node: Node
@@ -39,20 +39,6 @@ export function transformVueJsxVapor(
3939
})
4040
postCallbacks = rootNodes[0].postCallbacks!
4141
}
42-
else if (
43-
parent?.type === 'JSXAttribute'
44-
&& node.type === 'JSXExpressionContainer'
45-
&& /("|<.*?\/.*?>)/.test(s.sliceNode(node.expression))
46-
) {
47-
rootNodes.unshift({
48-
node: parent.name.name === 'v-for' && node.expression.type === 'BinaryExpression'
49-
? node.expression.right
50-
: node.expression,
51-
postCallbacks: [],
52-
isAttributeValue: true,
53-
})
54-
postCallbacks = rootNodes[0].postCallbacks!
55-
}
5642

5743
if (
5844
node.type === 'JSXElement'
@@ -80,21 +66,32 @@ export function transformVueJsxVapor(
8066
}
8167
else if (node.type === 'JSXAttribute') {
8268
let name = s.sliceNode(node.name)
83-
if (/^on[A-Z]/.test(name)) {
84-
name = name.replace(/^(?:on)([A-Z])/, (_, $1) => `@${$1.toLowerCase()}`)
85-
}
86-
else if (!name.startsWith('v-') && node.value?.type === 'JSXExpressionContainer') {
87-
name = `:${name}`
88-
}
69+
if (node.value?.type === 'JSXExpressionContainer') {
70+
if (/^on[A-Z]/.test(name)) {
71+
name = name.replace(/^(?:on)([A-Z])/, (_, $1) => `@${$1.toLowerCase()}`)
8972

90-
if (name.startsWith('v-') && node.value?.type === 'StringLiteral') {
91-
s.overwrite(node.value.start!, node.value.start! + 1, `"'`)
92-
s.overwrite(node.value.end! - 1, node.value.end!, `'"`)
93-
}
73+
if (!isFunctionExpression(node.value.expression))
74+
s.appendRight(node.value.expression.start!, '($event) =>')
75+
}
76+
else if (!name.startsWith('v-')) {
77+
name = `:${name}`
78+
}
9479

95-
if (node.value?.type === 'JSXExpressionContainer') {
9680
s.overwrite(node.value.start!, node.value.start! + 1, '"')
9781
s.overwrite(node.value.end! - 1, node.value.end!, '"')
82+
83+
rootNodes.unshift({
84+
node: name === 'v-for' && node.value.expression.type === 'BinaryExpression'
85+
? node.value.expression.right
86+
: node.value.expression,
87+
postCallbacks: [],
88+
isAttributeValue: true,
89+
})
90+
postCallbacks = rootNodes[0].postCallbacks!
91+
}
92+
else if (node.value?.type === 'StringLiteral' && name.startsWith('v-')) {
93+
s.overwrite(node.value.start!, node.value.start! + 1, `"'`)
94+
s.overwrite(node.value.end! - 1, node.value.end!, `'"`)
9895
}
9996

10097
postCallbacks.unshift(() =>
@@ -131,14 +128,10 @@ export function transformVueJsxVapor(
131128
s.overwrite(node.start!, node.start! + 1, '<component :is="__createTextVNode(')
132129
s.overwrite(node.end! - 1, node.end!, ')" />')
133130

134-
if (
135-
/("|<.*?\/.*?>)/.test(s.sliceNode(node.expression))
136-
) {
137-
rootNodes.unshift({
138-
node: node.expression,
139-
isAttributeValue: true,
140-
})
141-
}
131+
rootNodes.unshift({
132+
node: node.expression,
133+
isAttributeValue: true,
134+
})
142135
hasTextNode = true
143136
}
144137
}

src/core/v-for.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { MagicString } from '@vue-macros/common'
22
import type { CallExpression, Node } from '@babel/types'
33
import type { RootNodes } from './transform'
4-
import { overwrite } from './common'
4+
import { isFunctionExpression, overwrite } from './common'
55

66
export function transformVFor(
77
node: CallExpression,
@@ -11,8 +11,7 @@ export function transformVFor(
1111
) {
1212
const { callee, arguments: [argument] } = node
1313
if (
14-
argument.type !== 'FunctionExpression'
15-
&& argument.type !== 'ArrowFunctionExpression'
14+
!isFunctionExpression(argument)
1615
|| callee.type !== 'MemberExpression'
1716
)
1817
return

0 commit comments

Comments
 (0)