1.问题: v-if和v-for同时使用,那个优先级更高
2.分析
<template>
<p v-for="child in children" v-if="isFolder">{{child.title}}</p>
</template>
const app = new Vue({... })
console.log(app.$options.render);
从打印输出可以看出,_l 循环遍历的for ,里面再执行(isFolder)? 条件判断。
(function anonymous(
) {
with(this){return _c('div',{attrs:{"id":"demo"}},[_c('h1',[_v("xxx")]),_v(" "),
_l((children),function(child){return (isFolder)?_c('p',
[_v(_s(child.title))]):_e()})],2)}
})
vue会先将template模板 编译成AST抽象语法树。 从源码compiler/codegen/index.js 分析。 在genElement方法
export function genElement (el: ASTElement, state: CodegenState): string {
if (el.parent) {
el.pre = el.pre || el.parent.pre
}
if (el.staticRoot && !el.staticProcessed) {
return genStatic(el, state)
} else if (el.once && !el.onceProcessed) {
return genOnce(el, state)
} else if (el.for && !el.forProcessed) { //1.for命令优先执行
return genFor(el, state)
} else if (el.if && !el.ifProcessed) {//2.这里才执行if
return genIf(el, state)
} else if (el.tag === 'template' && !el.slotTarget && !state.pre) {
return genChildren(el, state) || 'void 0'
} else if (el.tag === 'slot') {
return genSlot(el, state)
} else {
...}
3.结论:
- 在源码中分析我们得出,vue把模板编译成AST抽象语法树时,genElement方法是先执行genFor方法,再执行genIf。所以for优先。
- 由于for先执行,无论如何判断,循环都会执行,浪费了性能。
4.优化方案:
- 把if提取到for的外部,优先判断。
- 如果出现在条件内部,可以提前把整个list 先过滤一遍,再交给template循环。(可以使用计算属性优化下次访问数组的效率)