Vue中v-if和v-for的优先级

748 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

当同个元素中包含了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先被执行了,在每个循环中再进行条件判断。

结论:

  1. 由render函数可以看出v-for优先于v-if被解析。
  2. 如果同时出现,会报错This 'v-if' should be moved to the wrapper element,每次都会先执行循环,再判断条件,无论如何循环都不能避免,浪费了性能。
  3. 要避免出现这种情况,则在外层嵌套template进行v-if判断,内层再进行v-for循环。