v-if和v-for哪个优先级更高?

分析:

此题考查常识,文档中曾有详细说明v2|v3;也是一个很好的实践题目,项目中经常会遇到,能够看出面试者应用能力。

思路分析:总分总模式

  1. 先给出结论
  2. 为什么是这样的
  3. 它们能放一起吗
  4. 如果不能,那应该怎样
  5. 总结

回答范例:

  1. Vue 2 中,v-for 优先于 v-if 被解析;但在 Vue 3 中,则完全相反,v-if 的优先级高于 v-for
  2. 我曾经做过实验,把它们放在一起,输出的渲染函数中可以看出会先执行循环再判断条件
  3. 实践中也不应该把它们放一起,因为哪怕我们只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表。
  4. 通常有两种情况下导致我们这样做:

    • 为了过滤列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。此时定义一个计算属性 (比如 activeUsers),让其返回过滤后的列表即可。
    • 为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。此时把 v-if 移动至容器元素上 (比如 ulol)即可。
  5. 文档中明确指出永远不要把 v-ifv-for 同时用在同一个元素上,显然这是一个重要的注意事项。
  6. 看过源码里面关于代码生成的部分,

知其所以然:

Vue 2 中做个测试,test.html
两者同级时,渲染函数如下:

ƒ anonymous(
) {
with(this){return _c('div',{attrs:{"id":"app"}},_l((items),function(item){return (item.isActive)?_c('div',{key:item.id},[_v("\n      "+_s(item.name)+"\n    ")]):_e()}),0)}
}

Vue 3 中做个测试,test-v3.html
两者同级时,渲染函数如下:

(function anonymous(
) {
const _Vue = Vue

return function render(_ctx, _cache) {
  with (_ctx) {
    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString, createCommentVNode: _createCommentVNode } = _Vue

    return shouldShowUsers
      ? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(items, (item) => {
          return (_openBlock(), _createElementBlock("div", { key: item.id }, _toDisplayString(item.name), 1 /* TEXT */))
        }), 128 /* KEYED_FRAGMENT */))
      : _createCommentVNode("v-if", true)
  }
}
})

源码中找答案:
Vue 2compiler/codegen/index.js
Vue 3compiler-core/src/codegen.ts

最后修改:2025 年 01 月 23 日
如果觉得我的文章对你有用,请随意赞赏