小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
当同个元素中包含了v-if和v-for时,哪个指令会先执行呢?这种操作是否合理呢? 我们先写个组件,在div中同时设置v-if和v-for,在mounted生命周期中打印一下render函数:
<template>
<div class="hello">
<div v-if="msg" v-for="item in arr">{{item + msg}}</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data() {
return {
msg: '元',
arr: [1,2,3]
}
},
mounted() {
console.log(this.$options.render);
}
}
</script>
运行组件后,我们会发现报了一个错误:This 'v-if' should be moved to the wrapper element。这个错误建议我们将v-if放到外层元素上。
接着我们来看一下打印出来的render函数:
var render = function() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c(
"div",
{ staticClass: "hello" },
// _vm._l是列表渲染函数,第一个参数是列表,第二个参数是每个循环执行的具体的函数,其中会进行条件判断,
//很明显会先执行v-for再执行v-if。
_vm._l(_vm.arr, function(item) {
return _vm.msg ? _c("div", [_vm._v(_vm._s(item + _vm.msg))]) : _vm._e()
}),
0
)
}
var staticRenderFns = []
render._withStripped = true
export { render, staticRenderFns }
很明显,v-for先被执行了,在每个循环中再进行条件判断。
结论:
- 由render函数可以看出v-for优先于v-if被解析。
- 如果同时出现,会报错
This 'v-if' should be moved to the wrapper element,每次都会先执行循环,再判断条件,无论如何循环都不能避免,浪费了性能。 - 要避免出现这种情况,则在外层嵌套template进行v-if判断,内层再进行v-for循环。