面试时候,被问到这样一道题目,v-for和v-if的优先级哪个更高,为什么。以及同时出现v-for和v-if的时候怎么优化性能最好呢?
解决问题最好的方式,当然是实践。

1、当v-if与v-for同级时

  1. // data数据
  2. const data = {
  3. items: [
  4. { id: 1, name: '吃西瓜' },
  5. { id: 2, name: '吃柠檬' }
  6. ]
  7. }
  8. const app = new Vue({
  9. el: '#demo',
  10. data() {
  11. return data
  12. },
  13. computed: {
  14. isTrue() {
  15. return this.items && this.items.length > 0
  16. }
  17. }
  18. })
  19. // console.log(app.$options.data)
  20. console.log(app.$options.render)

输出渲染函数render是这样的:

  1. ƒ anonymous() {
  2. with(this){return _c('div',{attrs:{"id":"demo"}},_l((items),function(item){return (isTrue)?_c('p',[_v(_s(item.name))]):_e()}),0)}
  3. }

_l是列表渲染函数,输出所有children
return的最终结果是,做的isTrue的判断
从上面的render我们看出,先执行的v-for然后每次v-for中都进行了isTrue的判断(浪费性能)

2、v-if放入template

代码修改一下:

  1. <template v-if="isTrue">
  2. <p v-for="item in items">{{item.name}}</p>
  3. </template>

此时我们再次输出render函数:

  1. ƒ anonymous(
  2. ) {
  3. with(this){return _c('div',{attrs:{"id":"demo"}},[(isTrue)?_l((items),function(item){return _c('p',[_v(_s(item.name))])}):_e()],2)}
  4. }

我们看到render函数变化了
v-if被解析为了三元运算符进行了判断:
[(isTrue)?_l((items)

此时先进行的v-if的判断,当为true才会去循环遍历数组(nice!)

从上面两个小demo我们不难发现:

结论:

  1. v-for的优先级要高于v-if
  2. 当两者同时出现,我们要将v-if提取出来,用一个template标签
  3. 当列表中每一项带有显隐字段,不得不同时嵌套v-if时候,可以用计算属性先过滤一下


3、查看一下源码

github地址在这里:https://github.com/vuejs/vue

我们找到文件:complier/codegen/index.js

image.png

我们看节点顺序是这样的:静态节点、once、for、if

通过源码我们也可以看到v-for的优先级是高于v-if的

4、循环列表项中存在显隐属性

当list中存在某个属性isTrue来控制渲染时候,我们需要在computed中计算一下将需要渲染的留下即可,这样可以起到性能优化的作用

demo的git地址:https://github.com/taoorange/vue2-knowledge-points.git

视频地址:

点击查看【bilibili】