此题考查常识,文档中曾有详细说明v2|v3;也是一个很好的实践题目,项目中经常会遇到,能够看出面试者应用能力。
在 Vue 2
中,v-for
优先于 v-if
被解析;但在 Vue 3
中,则完全相反,v-if
的优先级高于 v-for
。
我曾经做过实验,把它们放在一起,输出的渲染函数中可以看出会先执行循环再判断条件
实践中也不应该把它们放一起,因为哪怕我们只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表。
通常有两种情况下导致我们这样做:
为了过滤列表中的项目 (比如 v-for="user in users" v-if="user.isActive"
)。此时定义一个计算属性 (比如 activeUsers
),让其返回过滤后的列表即可。
为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers"
)。此时把 v-if
移动至容器元素上 (比如 ul
、ol
)即可。
文档中明确指出永远不要把 v-if
和 v-for
同时用在同一个元素上,显然这是一个重要的注意事项。
看过源码里面关于代码生成的部分,
在 Vue 2
中做个测试,
两者同级时,渲染函数如下:
ƒ 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
中做个测试,
两者同级时,渲染函数如下:
(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 2
:compiler/codegen/index.js
Vue 3
:compiler-core/src/codegen.ts
本文作者:毛超颖
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!