跳到主要内容位置

Vue 3.x 列表渲染 v-for 指令使用方法

张旭乾
软件工程师 / B站UP主

这篇文章我们来看一下在 vue 中展示列表内容。在前端开发中,经常会有展示列表的需求,例如博客列表,任务列表等等,那么 vue 中提供了 v-for 指令,来让我们方便的展示列表数据。

展示纯数组数据

我们知道,data() 函数返回的对象中,它的属性可以是任何类型,那么要展示列表数据,最合适的就是数组类型了:

data() {
return {
todos: ["把项目做完", "去超市购物", "看10分钟的书"],
};
},

假设我们要把 todos (待办事项)数组渲染到由 ul 和 li 构成的无序列表中,那么我们可以先定好结构:

<div id="app">
<ul>
<li></li>
</ul>
</div>

这里,ul 只需要渲染一次,而 todo 内容需要通过重复多次 li 标签来进行渲染:

<div id="app">
<ul>
<li>把项目做完</li>
<li>去超市购物</li>
<li>看10分钟的书</li>
</ul>
</div>

而使用 vue 提供的 v-for 指令,则可以只写一个 li 标签,在它里边使用 v-for 属性遍历 todos 数组:

<ul>
<li v-for="todo in todos">{{ todo }}</li>
</ul>

v-for 指令后面的值可以认为是一个 JavaScript 表达式,跟 for...in 循环类似,在关键字 in 的后面是要遍历的数组,前边则是给每个数组元素起的变量名字,可以在 li 开合标签中间,使用两个大括号引用,这样就根据数组的长度,生成了对应数量的 li 元素。

访问索引

如果想在遍历的时候,访问当前遍历的索引,那么我们可以在 in 的前边,在定义一个变量,例如叫作 index,放到 todo 变量的后面,并用逗号隔开,最后再使用小括号括起来:

<li v-for="(todo, index) in todos">{{index}}. {{ todo }}</li>

这样可以直接在后面访问 index 变量访问索引,不过索引是从 0 开始的,如果想让它从 1 开始显示,那么可以直接在两个大括号之间使用 JavaScript 表达式,给 index + 1:

{{ index + 1 }}

是的,vue 的 html 模板插值或者指令中,可以直接使用 JavaScript 表达式。

展示对象数组数据

如果要在 v-for 中遍历数组对象,也就是由对象构成的数组:

data() {
return {
todos: [
{
content: "把项目做完",
complete: true,
},
{
content: "去超市购物",
complete: false,
},
{
content: "看10分钟的书",
complete: false,
},
],
};
},

那么可以使用同样的方法,使用 v-for 遍历,只是在模板插值中访问对象中的内容时,需要使用对象访问语法,跟在 JavaScript 中访问对象一样:

<li v-for="todo in todos">
<input type="checkbox" :checked="todo.complete" />{{todo.content}}
</li>

示例

好,在介绍完 v-for 的用法之后,我们来看一个具体的示例。这里我们渲染一个待办事项列表。还是使用之前我们创建好的 vue 模板项目,在 index.js 中,我们先定义一个普通数组 todos:

const app = Vue.createApp({
data() {
return {
todos: ["把项目做完", "去超市购物", "看10分钟的书"],
};
},
});
app.mount("#app");

里边有三项待办事项,接下来打开 index.html 文件,在 id 为 app 的 div 中,定义一个 ul 无序列表,然后在里边定义一个 li 元素,在 li 元素里边,我们使用 v-for 指令,这里:

  • v-for 指令的值我们写上 todo in todos。
  • todos 就是要遍历的数组,todo 是给遍历到的数组元素起个名字,方便后面引用。
  • li 开合标签中间,使用模板插值语法,两个大括号,引用 todo 变量的值。
<ul>
<li v-for="todo in todos">{{ todo }}</li>
</ul>

这样就渲染出了待办事项列表。

访问索引

如果要给待办事项加上序号,可以在 v-for 指令中获取当前遍历到的索引:

<li v-for="(todo, index) in todos">{{index + 1}}. {{ todo }}</li>

这里直接在 todo 后面,加上一个逗号,再定义一个 index 变量,这个名字可以随便起,它就是当前遍历到的索引,别忘了把这两个变量放到一个小括号里。后面在模板插值中,可以直接给 index 加 1,让序号从 1 开始。这样就渲染了带序号的待办事项列表。

遍历对象数组

如果待办事项是通过对象的形式定义的,它有待办事项内容 content 和是否已完成 complete 两个属性,例如这样一组数据:

data() {
return {
todos: [
{
content: "把项目做完",
complete: true,
},
{
content: "去超市购物",
complete: false,
},
{
content: "看10分钟的书",
complete: false,
},
],
};
},

并且呢,在 html 中,我们根据待办是否已完成,来显示复选框,如果已完成,那么复选框会打勾,如果没有完成,那么复选框则是未选中的状态。那么我们先在 li 中,定义一个复选框:

<li v-for="todo in todos"><input type="checkbox" />{{ todo }}</li>

这个时候,遍历到的 todo 是一个对象了,如果直接使用 {{ todo }}会直接把整个对象转换成字符串进行展示,这时我们可以直接使用 todo.content 来访问 todo 对象的 content 属性值,跟在 JavaScript 中访问对象是一样的:

<li v-for="todo in todos"><input type="checkbox" />{{ todo.content }}</li>

现在,todo 的内容显示出来了,但是复选框还没有根据 todo 是否已完成,来显示选中或未选中状态。我们知道,在普通的 html 中,要让一个复选框变为选中状态,只需要给它加一个 checked 属性:

<input type="checkbox" checked />

我们需要根据 todo 的 complete 属性值来决定要不要添加 checked 这个属性。这就需要用到之前学习的 v-bind 指令了,不过,这里的 checked 似乎只有一个属性名,但是没有属性值,那要怎么绑定呢?其实这种单独属性名的形式,就相当于值为 true:

<input type="checkbox" checked="true" />

如果没有这个属性,那么就相当于这个属性值为 false:

<input type="checkbox" checked="false" />

那么根据这个特点,我们可以使用 v-bind 或简写形式,直接把 todo 的 complete 的属性值,绑定到 checked 属性:

<li v-for="todo in todos">
<input type="checkbox" :checked="todo.complete" />{{todo.content}}
</li>

这样,复选框就会根据 todo 的 complete 属性值,来展示为选中状态或未选中状态了。

小结

这个就是在 vue 中展示列表数据的方法,使用 v-for 指令,遍历 data 中数组类型的属性,并且还可以访问索引和遍历对象数组。另外对于 vue 的模板,在插值中可以直接使用 JavaScript 表达式,对某个变量进行数学运算,或访问对象类型的变量。对于只有单独的一个属性名的情况,也利用 v-bind 进行数据绑定。

提示

一系列的课程让你成为高级前端工程师。课程覆盖工作中所有常用的知识点和背后的使用逻辑,示例全部都为工作项目简化而来,学完即可直接上手开发!

即使你已经是高级前端工程师,在课程里也可能会发现新的知识点和技巧,让你的工作更加轻松!

《React 完全指南》课程,包含 React、React Router 和 Redux 详细介绍,所有示例改编自真实工作代码。点击查看详情。

《Vue 3.x 全家桶完全指南与实战》课程,包括 Vue 3.x、TypeScript、Vue Router 4.x、Vuex 4.x 所有初级到高级的语法特性详解,让你完全胜任 Vue 前端开发的工作。点击查看详情。

《React即时通信UI实战》课程,利用 Storybook、Styled-components、React-Spring 打造属于自己的组件库。

《JavaScript 基础语法详解》本人所著图书,包含 JavaScript 全面的语法知识和新特性, 可在京东、当当、淘宝等各大电商购买