Skip to content

Commit 2967745

Browse files
committed
refactor: use early return style in v-for
1 parent c7620c1 commit 2967745

File tree

1 file changed

+114
-114
lines changed
  • packages/compiler-core/src/transforms

1 file changed

+114
-114
lines changed

packages/compiler-core/src/transforms/vFor.ts

Lines changed: 114 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -39,132 +39,132 @@ import { PatchFlags, PatchFlagNames } from '@vue/shared'
3939
export const transformFor = createStructuralDirectiveTransform(
4040
'for',
4141
(node, dir, context) => {
42-
if (dir.exp) {
43-
const parseResult = parseForExpression(
44-
// can only be simple expression because vFor transform is applied
45-
// before expression transform.
46-
dir.exp as SimpleExpressionNode,
47-
context
42+
if (!dir.exp) {
43+
context.onError(
44+
createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc)
4845
)
46+
return
47+
}
4948

50-
if (parseResult) {
51-
const { helper, addIdentifiers, removeIdentifiers, scopes } = context
52-
const { source, value, key, index } = parseResult
49+
const parseResult = parseForExpression(
50+
// can only be simple expression because vFor transform is applied
51+
// before expression transform.
52+
dir.exp as SimpleExpressionNode,
53+
context
54+
)
5355

54-
// create the loop render function expression now, and add the
55-
// iterator on exit after all children have been traversed
56-
const renderExp = createCallExpression(helper(RENDER_LIST), [source])
57-
const keyProp = findProp(node, `key`)
58-
const fragmentFlag = keyProp
59-
? PatchFlags.KEYED_FRAGMENT
60-
: PatchFlags.UNKEYED_FRAGMENT
61-
const codegenNode = createSequenceExpression([
62-
createCallExpression(helper(OPEN_BLOCK)),
63-
createCallExpression(helper(CREATE_BLOCK), [
64-
helper(FRAGMENT),
65-
`null`,
66-
renderExp,
67-
fragmentFlag +
68-
(__DEV__ ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``)
69-
])
70-
]) as ForCodegenNode
56+
if (!parseResult) {
57+
context.onError(
58+
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc)
59+
)
60+
return
61+
}
7162

72-
context.replaceNode({
73-
type: NodeTypes.FOR,
74-
loc: dir.loc,
75-
source,
76-
valueAlias: value,
77-
keyAlias: key,
78-
objectIndexAlias: index,
79-
children:
80-
node.tagType === ElementTypes.TEMPLATE ? node.children : [node],
81-
codegenNode
82-
})
63+
const { helper, addIdentifiers, removeIdentifiers, scopes } = context
64+
const { source, value, key, index } = parseResult
8365

84-
// bookkeeping
85-
scopes.vFor++
86-
if (!__BROWSER__ && context.prefixIdentifiers) {
87-
// scope management
88-
// inject identifiers to context
89-
value && addIdentifiers(value)
90-
key && addIdentifiers(key)
91-
index && addIdentifiers(index)
92-
}
66+
// create the loop render function expression now, and add the
67+
// iterator on exit after all children have been traversed
68+
const renderExp = createCallExpression(helper(RENDER_LIST), [source])
69+
const keyProp = findProp(node, `key`)
70+
const fragmentFlag = keyProp
71+
? PatchFlags.KEYED_FRAGMENT
72+
: PatchFlags.UNKEYED_FRAGMENT
73+
const codegenNode = createSequenceExpression([
74+
createCallExpression(helper(OPEN_BLOCK)),
75+
createCallExpression(helper(CREATE_BLOCK), [
76+
helper(FRAGMENT),
77+
`null`,
78+
renderExp,
79+
fragmentFlag + (__DEV__ ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``)
80+
])
81+
]) as ForCodegenNode
82+
83+
context.replaceNode({
84+
type: NodeTypes.FOR,
85+
loc: dir.loc,
86+
source,
87+
valueAlias: value,
88+
keyAlias: key,
89+
objectIndexAlias: index,
90+
children: node.tagType === ElementTypes.TEMPLATE ? node.children : [node],
91+
codegenNode
92+
})
9393

94-
return () => {
95-
scopes.vFor--
96-
if (!__BROWSER__ && context.prefixIdentifiers) {
97-
value && removeIdentifiers(value)
98-
key && removeIdentifiers(key)
99-
index && removeIdentifiers(index)
100-
}
94+
// bookkeeping
95+
scopes.vFor++
96+
if (!__BROWSER__ && context.prefixIdentifiers) {
97+
// scope management
98+
// inject identifiers to context
99+
value && addIdentifiers(value)
100+
key && addIdentifiers(key)
101+
index && addIdentifiers(index)
102+
}
101103

102-
// finish the codegen now that all children have been traversed
103-
let childBlock
104-
const isTemplate = isTemplateNode(node)
105-
const slotOutlet = isSlotOutlet(node)
106-
? node
107-
: isTemplate &&
108-
node.children.length === 1 &&
109-
isSlotOutlet(node.children[0])
110-
? node.children[0]
111-
: null
112-
const keyProperty = keyProp
113-
? createObjectProperty(
114-
`key`,
115-
keyProp.type === NodeTypes.ATTRIBUTE
116-
? createSimpleExpression(keyProp.value!.content, true)
117-
: keyProp.exp!
118-
)
119-
: null
120-
if (slotOutlet) {
121-
// <slot v-for="..."> or <template v-for="..."><slot/></template>
122-
childBlock = slotOutlet.codegenNode!
123-
if (isTemplate && keyProperty) {
124-
// <template v-for="..." :key="..."><slot/></template>
125-
// we need to inject the key to the renderSlot() call.
126-
// the props for renderSlot is passed as the 3rd argument.
127-
injectProp(childBlock, keyProperty, context)
128-
}
129-
} else if (isTemplate) {
130-
// <template v-for="...">
131-
// should generate a fragment block for each loop
132-
childBlock = createBlockExpression(
133-
createCallExpression(helper(CREATE_BLOCK), [
134-
helper(FRAGMENT),
135-
keyProperty ? createObjectExpression([keyProperty]) : `null`,
136-
node.children
137-
]),
138-
context
139-
)
140-
} else {
141-
// Normal element v-for. Directly use the child's codegenNode
142-
// arguments, but replace createVNode() with createBlock()
143-
let codegenNode = node.codegenNode as ElementCodegenNode
144-
if (codegenNode.callee === APPLY_DIRECTIVES) {
145-
codegenNode.arguments[0].callee = helper(CREATE_BLOCK)
146-
} else {
147-
codegenNode.callee = helper(CREATE_BLOCK)
148-
}
149-
childBlock = createBlockExpression(codegenNode, context)
150-
}
104+
return () => {
105+
scopes.vFor--
106+
if (!__BROWSER__ && context.prefixIdentifiers) {
107+
value && removeIdentifiers(value)
108+
key && removeIdentifiers(key)
109+
index && removeIdentifiers(index)
110+
}
151111

152-
renderExp.arguments.push(
153-
createFunctionExpression(
154-
createForLoopParams(parseResult),
155-
childBlock,
156-
true /* force newline */
157-
)
112+
// finish the codegen now that all children have been traversed
113+
let childBlock
114+
const isTemplate = isTemplateNode(node)
115+
const slotOutlet = isSlotOutlet(node)
116+
? node
117+
: isTemplate &&
118+
node.children.length === 1 &&
119+
isSlotOutlet(node.children[0])
120+
? node.children[0]
121+
: null
122+
const keyProperty = keyProp
123+
? createObjectProperty(
124+
`key`,
125+
keyProp.type === NodeTypes.ATTRIBUTE
126+
? createSimpleExpression(keyProp.value!.content, true)
127+
: keyProp.exp!
158128
)
129+
: null
130+
if (slotOutlet) {
131+
// <slot v-for="..."> or <template v-for="..."><slot/></template>
132+
childBlock = slotOutlet.codegenNode!
133+
if (isTemplate && keyProperty) {
134+
// <template v-for="..." :key="..."><slot/></template>
135+
// we need to inject the key to the renderSlot() call.
136+
// the props for renderSlot is passed as the 3rd argument.
137+
injectProp(childBlock, keyProperty, context)
159138
}
160-
} else {
161-
context.onError(
162-
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc)
139+
} else if (isTemplate) {
140+
// <template v-for="...">
141+
// should generate a fragment block for each loop
142+
childBlock = createBlockExpression(
143+
createCallExpression(helper(CREATE_BLOCK), [
144+
helper(FRAGMENT),
145+
keyProperty ? createObjectExpression([keyProperty]) : `null`,
146+
node.children
147+
]),
148+
context
163149
)
150+
} else {
151+
// Normal element v-for. Directly use the child's codegenNode
152+
// arguments, but replace createVNode() with createBlock()
153+
let codegenNode = node.codegenNode as ElementCodegenNode
154+
if (codegenNode.callee === APPLY_DIRECTIVES) {
155+
codegenNode.arguments[0].callee = helper(CREATE_BLOCK)
156+
} else {
157+
codegenNode.callee = helper(CREATE_BLOCK)
158+
}
159+
childBlock = createBlockExpression(codegenNode, context)
164160
}
165-
} else {
166-
context.onError(
167-
createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc)
161+
162+
renderExp.arguments.push(
163+
createFunctionExpression(
164+
createForLoopParams(parseResult),
165+
childBlock,
166+
true /* force newline */
167+
)
168168
)
169169
}
170170
}

0 commit comments

Comments
 (0)