列表渲染,其实给人的感觉就是 JavaScript 中的 for
循环,只不过将其提取到 HTML 模板层面了,将其指令化,本质还是 for 循环。
v-for
把一个数组对应为一组元素我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items 是源数据数组,而 item
则是被迭代的数组元素的别名。
同样,我们在 src/views/TemplateM.vue
写下如下代码:
<template>
<div class="template-m-wrap">
<ul>
<li :key="index" v-for="(item, index) in items">{{item.name}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "TemplateM",
data() {
return {
items: [
{
name: 'Ken',
},
{
name: 'coder'
},
{
name: 'nana'
}
]
};
},
};
</script>
查看浏览器效果如下:
你也可以用of
替代in
作为分隔符,因为它更接近 JavaScript 迭代器的语法:
<template>
<div class="template-m-wrap">
<ul>
<li :key="index" v-for="(item, index) of items">{{item.name}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "TemplateM",
data() {
return {
items: [
{
name: 'Ken',
},
{
name: 'coder'
},
{
name: 'nana'
}
]
};
},
};
</script>
查看浏览效果如下:
v-for
里使用对象
你也可以用v-for
来遍历一个对象的 property。
<template>
<div class="template-m-wrap">
<ul>
<li v-for="(item) in items">{{item}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "TemplateM",
data() {
return {
items: {
name: 'Ken',
hobby: 'Coder, 投资理财, 写教程',
sex: '男'
}
};
},
};
</script>
查看浏览效果如下:
你也可以提供第二个的参数为 property 名称 (也就是键名)
<li :key="name" v-for="(item, name) in items">{{name}} - {{item}}</li>
效果如下:
还可以用第三个参数作为索引:
<li :key="name" v-for="(item, name, index) in items">{{name}} - {{item}} - {{index}}</li>
查看效果如下:
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。
这个默认的模式是高效的,但是「只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出」。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
attribute:
<template>
<div class="template-m-wrap">
<div v-for="item in items" :key="item.id">
<!-- content -->
我的名字是 {{item.name}} - 性别 {{item.sex}} - 爱好是 {{item.hobby}}
</div>
</div>
</template>
<script>
export default {
name: "TemplateM",
data() {
return {
items: [
{
name: "Ken",
hobby: "Coder, 投资理财, 写教程",
sex: "男",
id: 1,
},
{
name: "Nana",
hobby: "Coder, 投资理财, 写教程",
sex: "女",
id: 2,
},
],
};
},
};
</script>
查看浏览效果如下:
建议尽可能在使用 v-for
时提供 key
attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
因为它是 Vue 识别节点的一个通用机制,key
并不仅与 v-for
特别关联。后面我们将在指南中看到,它还具有其它用途。
提示
不要使用对象或数组之类的非基本类型值作为 v-for
的 key。请用字符串或数值类型的值。
<template>
在使用 v-for
类似于 v-if
,你也可以利用带有 v-for
的 <template>
来循环渲染一段包含多个元素的内容。比如:
<template>
<div class="template-m-wrap">
<template v-for="item in items">
<div :key="item.id">
<!-- content -->
我的名字是 {{ item.name }} - 性别 {{ item.sex }} - 爱好是
{{ item.hobby }}
</div>
</template>
</div>
</template>
<script>
export default {
name: "TemplateM",
data() {
return {
items: [
{
name: "Ken",
hobby: "Coder, 投资理财, 写教程",
sex: "男",
id: 1,
},
{
name: "Nana",
hobby: "Coder, 投资理财, 写教程",
sex: "女",
id: 2,
},
],
};
},
};
</script>
其实你在写代码时候,就会发现 template
模板可以使用 v-for
循环,但是不能使用 :key
绑定唯一属性,会提示你绑定在 template->div
:
<template v-for="item in items">
<div :key="item.id">
<!-- content -->
我的名字是 {{ item.name }} - 性别 {{ item.sex }} - 爱好是
{{ item.hobby }}
</div>
</template>
效果如下:
v-for
与 v-if
一同使用
当它们处于同一节点,v-for
的优先级比 v-if
更高,这意味着 v-if
将分别重复运行于每个 v-for
循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:
<li :key="index" v-for="(item, index) in items" v-if="!item.isComplete">
{{ item.name }}
</li>
上面的代码将只渲染未完成的 item。
控制台报错:
而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 [`) 上。如:
<ul v-if="items.length">
<li :key="index" v-for="(item, index) in items">
{{ item.name }}
</li>
</ul>
<p v-else>No todos left!</p>
查看浏览效果如下:
v-for
这一点我们后面再讲