在实际开发中,会遇到这样的情况,需要先判断是否满足条件,然后再循环渲染列表,此时就涉及到了 v-if
和 v-for
一起使用的问题。相信你们也遇到过,当将两者同时都写在一个标签里面的时候,就会出现红线警告,原因是什么呢?怎么去解决呢?下面本文就这个问题进行解释。
一、作用
v-if
指令用于在满足条件下的渲染内容。这块内容只会在表达式为true
的时候才会被渲染。
v-for
指令是用一个数组来渲染列表。v-for
指令需要使用 item in list
形式的特殊语法,其中 item
是迭代的每一项的元素,list
是被循环的源数组。
在 v-for
的时候,建议设置 key
的值,并且保证每一个 key
的值是独一无二的,这样便于 diff
算法进行优化。
这两者在用法上:
<div v-if="isShow" />我被显示了吗?</div>
<li v-for="item in list" :key="item.id">
{{ item.label }}
</li>
二、优先级
v-if
和 v-for
都是 vue
模板系统中的指令。
在 vue
模板编译的时候,会将指令系统转化成可以执行的 render
函数。
实例
p
标签同时使用 v-if
和 v-for
<div id="app">
<p v-if="show" v-for="item in list">
{{ item.title }}
</p>
</div>
创建 vue
实例,存放 show
和 list
数据
const app = new Vue({
el: "#app",
data() {
return {
list: [
{ title: "foo" },
{ title: "baz" }]
}
},
computed: {
show() {
return this.list && this.list.length > 0
}
}
})
模板指令的代码都会生成在 render
函数中,通过 app.$options.render
就能得到渲染函数。
ƒ anonymous() {
with (this) { return
_c('div', { attrs: { "id": "app" } },
_l((list), function (item)
{ return (show) ? _c('p', [_v("\n" + _s(item.title) + "\n")]) : _e() }), 0) }
}
_l
是vue
的列表渲染函数,函数内部都会进行一次if判断
初步得到结论:v-for
优先级是比v-if
高。
再将v-for
与v-if
置于不同标签。
<div id="app">
<template v-if="show">
<p v-for="item in list">{{item.title}}</p>
</template>
</div>
再输出render
函数
ƒ anonymous() {
with(this){return
_c('div',{attrs:{"id":"app"}},
[(show)?[_v("\n"),
_l((list),function(item){return _c('p',[_v(_s(item.title))])})]:_e()],2)}
}
这时候我们可以看到,v-for
与v-if
作用在不同标签时候,是先进行判断,再进行列表的渲染。
从上面两个例子可以看出,满足我们需求的是第二种,先对整体进行判断,然后再对list
进行循环渲染,而不是每次渲染都先循环再判断。
三、注意事项
1.不要把 v-if
和 v-for
同时作用在同一个元素上,会带来性能当面的浪费(每次渲染之前都会先循环再判断)。
2.避免出现作用在同一个元素上的情况,可以在外层嵌套一个 template
(页面渲染不会生成 DOM
节点),在这一层先进行 v-if
的判断,然后再内部进行 v-for
的循环。
<template v-if="show">
<p v-for="item in list">
</template>
3.如果出现条件在循环内部,则可以计算属性 computed
提前过滤掉哪些不需要显示的项。
computed: {
items: function() {
return this.list.filter(function (item) {
return item.show
})
}
}