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

77 lines
2.3 KiB
TypeScript
Raw Normal View History

import {
createStructuralDirectiveTransform,
traverseChildren
} from '../transform'
import {
NodeTypes,
ElementTypes,
ElementNode,
DirectiveNode,
IfBranchNode,
SimpleExpressionNode
} from '../ast'
import { createCompilerError, ErrorCodes } from '../errors'
2019-09-24 08:45:40 +08:00
import { processExpression } from './transformExpression'
2019-09-22 05:42:12 +08:00
export const transformIf = createStructuralDirectiveTransform(
/^(if|else|else-if)$/,
(node, dir, context) => {
2019-09-24 01:29:41 +08:00
if (!__BROWSER__ && context.prefixIdentifiers && dir.exp) {
// dir.exp can only be simple expression because vIf transform is applied
// before expression transform.
processExpression(dir.exp as SimpleExpressionNode, context)
}
if (dir.name === 'if') {
context.replaceNode({
type: NodeTypes.IF,
loc: node.loc,
branches: [createIfBranch(node, dir)]
})
} else {
// locate the adjacent v-if
const siblings = context.parent.children
2019-09-20 03:41:17 +08:00
const comments = []
2019-09-23 14:52:54 +08:00
let i = siblings.indexOf(node as any)
2019-09-20 03:41:17 +08:00
while (i-- >= -1) {
const sibling = siblings[i]
2019-09-20 03:41:17 +08:00
if (__DEV__ && sibling && sibling.type === NodeTypes.COMMENT) {
context.removeNode(sibling)
comments.unshift(sibling)
continue
}
2019-09-20 03:41:17 +08:00
if (sibling && sibling.type === NodeTypes.IF) {
// move the node to the if node's branches
context.removeNode()
const branch = createIfBranch(node, dir)
2019-09-20 03:41:17 +08:00
if (__DEV__ && comments.length) {
branch.children = [...comments, ...branch.children]
}
sibling.branches.push(branch)
// since the branch was removed, it will not be traversed.
// make sure to traverse here.
traverseChildren(branch, context)
} else {
2019-09-22 05:42:12 +08:00
context.onError(
createCompilerError(
dir.name === 'else'
? ErrorCodes.X_ELSE_NO_ADJACENT_IF
: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
node.loc
)
)
}
break
}
}
}
)
function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
return {
type: NodeTypes.IF_BRANCH,
loc: node.loc,
condition: dir.name === 'else' ? undefined : dir.exp,
children: node.tagType === ElementTypes.TEMPLATE ? node.children : [node]
}
}