Vue 中v-for和v-if
1. v-for和v-if的渲染优先级
首先:永远不要把 v-if 和 v-for 同时用在同一个元素上。
其次:当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,这句话代表着,当 v-if 和 v-for 同时出现。渲染函数会先执行到 v-for。我们的本意是根据用户权限来控制是否显示一个列表。但是如果代码如上的话 v-if 实际上是执行到了列表渲染的每一项。
如果遇到这种需求的话我们建议的写法是:
<div v-if = 'flag'>
<div v-for='(item) in lcList' :key='item.id' >
</div>
如果遇到必须写一起的话建议写法:
<div v-for='(item) in lcList' :key='item.id' v-if='item.userName'>
2. Vue3 v-if的实现原理
2.1 实现原理
直接在 Vue3 Template Explore 输入一个使用 v-if
指令的栗子:
<div v-if="visible"></div>
然后,由它编译生成的 render
函数会是这样:
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_ctx.visible)
? (_openBlock(), _createElementBlock("div", { key: 0 }))
: _createCommentVNode("v-if", true)
}
可以看到,一个简单的使用 v-if
指令的模版编译生成的 render
函数最终会返回一个三目运算表达式。首先,让我们先来认识一下其中几个变量和函数的意义:
_ctx
当前组件实例的上下文,即this
_openBlock()
和_createBlock()
用于构造Block Tree
和Block VNode
,它们主要用于靶向更新过程_createCommentVNode()
创建注释节点的函数,通常用于占位
显然,如果当 visible
为 false
的时候,会在当前模版中创建一个注释节点(也可称为占位节点),反之则创建一个真实节点(即它自己)。例如当 visible
为 false
时渲染到页面上会是这样:
在 Vue 中很多地方都运用了注释节点来作为占位节点,其目的是在不展示该元素的时候,标识其在页面中的位置,以便在
patch
的时候将该元素放回该位置。
那么,这个时候我想大家就会抛出一个疑问:当 visible
动态切换 true
或 false
的这个过程(派发更新)究竟发生了什么?
派发更新时 patch,更新节点。
2.2 小结
总体来看,v-if
指令的实现较为简单,基于数据驱动的理念,当 v-if
指令对应的 value
为 false
的时候会预先创建一个注释节点在该位置,然后在 value
发生变化时,命中派发更新的逻辑,对新旧组件树进行 patch
,从而完成使用 v-if
指令元素的动态显示隐藏。