Vue-源码解析v-for 和 v-if优先级
1、源码解析当v-for 和 v-if在同一级使用时,系统会报错This 'v-if' should be moved to the wrapper element,因为当它们处于同一节点,v-for的优先级比v-if更高。这种情况时,for循环还是会走下去。下面我们先从渲染函数再到源码进行分析:const VueTemplateCompiler = require('vue-template-c
1、源码解析
当v-for 和 v-if在同一级使用时,系统会报错This 'v-if' should be moved to the wrapper element
,因为当它们处于同一节点,v-for的优先级比v-if更高
。这种情况时,for循环还是会走下去。下面我们先从渲染函数再到源码
进行分析:
const VueTemplateCompiler = require('vue-template-compiler')
const template = '<div v-for="item in 3" :key="item" v-if="false">{{ item }}</div>'
// 模版编译成render方法
const compile = VueTemplateCompiler.compile(template)
console.log(compile.render)
with (this) { return _l((3), function (item) { return (false) ? _c('div', { key: item }, [_v(_s(item))]) : _e() }) }
从渲染函数可以看出先进行for循环再在其内部进行条件判断,这明显是不符合性能优化的;我们再来看看源码的实现:在vue/src/compiler/codegen/index.js
中查看核心代码
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) { // v-for
return genFor(el, state)
} else if (el.if && !el.ifProcessed) { // v-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 {
// component or element
let code
if (el.component) {
code = genComponent(el.component, el, state)
} else {
let data
if (!el.plain || (el.pre && state.maybeComponent(el))) {
data = genData(el, state)
}
const children = el.inlineTemplate ? null : genChildren(el, state, true)
code = `_c('${el.tag}'${
data ? `,${data}` : '' // data
}${
children ? `,${children}` : '' // children
})`
}
// module transforms
for (let i = 0; i < state.transforms.length; i++) {
code = state.transforms[i](el, code)
}
return code
}
}
可以看出,在解析时先解析v-for再解析v-if
2、解决方案
1、当不满足条件时跳过循环的执行,那么可以将 v-if 置于v-for的外层元素(可见报错提示信息:This 'v-if' should be moved to the wrapper element
)
2、 如果条件出现在循环内部,则可通过计算属性对数据源fliter
进行操作过滤掉不满足条件的数据(可见报错提示信息:'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'
)。
更多推荐
所有评论(0)