先说结论:在vue2中v-for的优先级高于v-if,而在vue3中v-if的优先级要高于v-for。
接下来会通过对下面这段代码在vue2和vue3中的编译产物的说明来解释v-if和v-for的优先级。
<div id="app">
<div v-for="item in [1, 2, 3, 4, 5]" v-if="item !== 2"></div>
</div>
在vue2中(vue2的演练场地址: https://v2.template-explorer.vuejs.org/)
从上面render函数中圈出来的部分可以看出,在 vue2 中,会先进行for循环,然后在每次循环中进行 item !== 2 的判断,如果为true会执行_c('div')函数进行正常渲染,为false则会执行_e()函数将不满足条件的节点注释掉,这就解释了为什么在 vue2 中 v-for 的优先级要高于 v-if。
上面最终渲染出来的节点只有1、3、4、5这4个节点,但由于是在每次循环中进行的if判断,最后还是会循环5次,这样就造成了性能浪费,这就是为什么在 vue2 中 v-for 和 v-if 不建议一起使用的原因。
在vue3中(vue3的演练场地址: https://play.vuejs.org/)
从上面render函数中圈出来的部分可以看出,在 vue3 中,会先进行 item !== 2 的判断,如果为 true 才会去进行for循环,如果为 false 则会执行 _createCommentVNode("v-if", true) 函数,创建一个注释节点,这就解释了为什么在 vue3 中 v-if 的优先级要高于 v-for。
我们在上面截图的左边部分可以看到 v-if 里面的 item 有一个报错的提示,我们先看下报错:
从上图中可以看出,提示我们 item 不存在。这是因为 v-for 和 v-if 一起使用时,vue3 会在底层帮我们将截图中的代码转换成下面的形式:由于 v-if 中的 item 在外层,而我们也没有定义 item 这个变量,所以会报错找不到 item。
<template>
<div id="app">
<template v-if="item !== 2">
<div v-for="item in [1, 2, 3, 4, 5]"></div>
</template>
</div>
</template>
终上所述:不管是在vue2还是vue3中,都不建议v-for和v-if在同一个标签中一起使用,如果遇到需要同时在一个标签中使用v-for和v-if的情况,可以使用计算属性 computed 去处理,以此得到你想要的数据。