📰 前言
众所周知,在 vue3
中 v-if
总是优先于 v-for
生效。
然而,在某些情况下,我们可能更希望 v-for
的优先级更高,
虽然 vue3
并没有提供直接修改指令优先级的方法,但是我们可以使用 AST(抽象语法树)
转换来实现这一点。
🌈 在线演示
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { transformForIf } from './transformForIf'
export default defineConfig({
plugins: [
vue({
template: { compilerOptions: { nodeTransforms: [transformForIf] } }
})
]
})
import { remove } from '@vue/shared'
import { NodeTransform, findDir, findProp } from '@vue/compiler-core'
const ELEMENT = 1
// 创建 template 节点
export const createTemplateNode = (props: BaseElementNode['props'], children: BaseElementNode['children'], loc: BaseElementNode['loc']): TemplateNode => ({
type: ELEMENT,
tagType: TEMPLATE,
tag: 'template',
props: props.filter(e => e),
children,
codegenNode: undefined,
ns: 0,
isSelfClosing: false,
loc
})
export const transformForIf: NodeTransform = node => {
if (node.type != ELEMENT) return
node.children.forEach((child, i) => {
if (child.type != ELEMENT) return
const VFor = findDir(child, 'for')
if (!VFor) return
const VIf = findDir(child, 'if')
if (!VIf) return
const key = findProp(child, 'key')
remove(child.props, VFor)
remove(child.props, VIf)
remove(child.props, key)
const templateIf = createTemplateNode([VIf], [child], VIf.loc)
const templateFor = createTemplateNode([VFor, key], [templateIf], VFor.loc)
node.children[i] = templateFor
})
}
🔺 以上就是完整代码了
🎃 让我们来试试效果
<template>
<div>
<span v-for="i in 10" v-if="i % 2">{{ i }}</span>
</div>
</template>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。