渲染 Vue 组件列表
在这一点上,我们已经拥有了一个完全工作的组件;现在我们准备将多个ToDoItem组件添加到我们的应用程序中。在本文中,我们将了解如何将一组待办事项数据添加到我们的App.vue组件中,然后我们将循环遍历这些数据并在ToDoItem组件内使用v-for指令显示它们。
| 先决条件 |
熟悉核心HTML、CSS和JavaScript语言,了解终端/命令行。 Vue 组件被编写为 JavaScript 对象(管理应用程序数据)和基于 HTML 的模板语法(映射到底层 DOM 结构)的组合。对于安装,以及使用 Vue 的一些更高级的功能(如单文件组件或渲染函数),您需要一个安装了 node + npm 的终端。 |
|---|---|
| 目标 | 学习如何循环遍历数据数组并在多个组件中渲染它。 |
使用 v-for 渲染列表
为了成为一个有效的待办事项列表,我们需要能够渲染多个待办事项。为此,Vue 有一个特殊的指令,v-for。这是一个内置的 Vue 指令,它允许我们在模板内包含一个循环,为数组中的每个项目重复渲染模板功能。我们将使用它来迭代待办事项数组并在我们的应用程序中以单独的ToDoItem组件显示它们。
添加一些要渲染的数据
首先,我们需要获取一个待办事项数组。为此,我们将向App.vue组件对象添加一个data属性,其中包含一个ToDoItems字段,其值为待办事项数组。虽然我们最终会添加一个添加新待办事项的机制,但我们可以先从一些模拟待办事项开始。每个待办事项都将由一个包含label和done属性的对象表示。
添加一些示例待办事项,类似于下面显示的那些。这样,您就可以使用v-for渲染一些可用数据。
export default {
name: "app",
components: {
ToDoItem,
},
data() {
return {
ToDoItems: [
{ label: "Learn Vue", done: false },
{ label: "Create a Vue project with the CLI", done: true },
{ label: "Have fun", done: true },
{ label: "Create a to-do list", done: false },
],
};
},
};
现在我们有了项目列表,我们可以使用v-for指令来显示它们。指令应用于像其他属性一样的元素。在v-for的情况下,您使用类似于 JavaScript 中for...in循环的特殊语法——v-for="item in items"——其中items是要迭代的数组,item是对数组中当前元素的引用。
v-for附加到您要重复的元素,并渲染该元素及其子元素。在本例中,我们希望为ToDoItems数组中的每个待办事项显示一个<li>元素。然后,我们希望将每个待办事项的数据传递给ToDoItem组件。
键属性
在这样做之前,还有一个关于与v-for一起使用的语法需要了解,即key属性。为了帮助 Vue 优化渲染列表中的元素,它尝试修补列表元素,以便它不会在每次列表更改时都重新创建它们。但是,Vue 需要帮助。为了确保它正确地重用列表元素,它需要在您附加v-for的相同元素上有一个唯一的“键”。
为了确保 Vue 可以准确地比较key属性,它们需要是字符串或数字值。虽然使用名称字段会很好,但此字段最终将由用户输入控制,这意味着我们无法保证名称是唯一的。但是,我们可以像在上一篇文章中一样使用nanoid()。
- 使用以下方法将
nanoid导入到您的App组件中,就像您使用ToDoItem组件一样:jsimport { nanoid } from "nanoid"; - 接下来,在您的
ToDoItems数组中的每个元素中添加一个id字段,并为每个元素分配一个"todo-" + nanoid()的值。App.vue中的<script>元素现在应该包含以下内容:jsimport ToDoItem from "./components/ToDoItem.vue"; import { nanoid } from "nanoid"; export default { name: "app", components: { ToDoItem, }, data() { return { ToDoItems: [ { id: "todo-" + nanoid(), label: "Learn Vue", done: false }, { id: "todo-" + nanoid(), label: "Create a Vue project with the CLI", done: true, }, { id: "todo-" + nanoid(), label: "Have fun", done: true }, { id: "todo-" + nanoid(), label: "Create a to-do list", done: false, }, ], }; }, }; - 现在,将
v-for指令和key属性添加到App.vue模板中的<li>元素中,如下所示:当您进行此更改时,html<ul> <li v-for="item in ToDoItems" :key="item.id"> <to-do-item label="My ToDo Item" :done="true"></to-do-item> </li> </ul><li>标签之间的每个 JavaScript 表达式除了其他组件属性外,还可以访问item值。这意味着我们可以将项目对象的字段传递给我们的ToDoItem组件——只需记住使用v-bind语法即可。这非常有用,因为我们希望我们的待办事项显示其label属性作为其标签,而不是“我的待办事项”的静态标签。此外,我们希望它们的选中状态反映其done属性,而不是始终设置为done="true"。 - 将
label="My ToDo Item"属性更新为:label="item.label",并将:done="true"属性更新为:done="item.done",如下面的上下文中所示:html<ul> <li v-for="item in ToDoItems" :key="item.id"> <to-do-item :label="item.label" :done="item.done"></to-do-item> </li> </ul>
现在,当您查看正在运行的应用程序时,它将显示待办事项及其正确的名称,如果您检查源代码,您会看到所有输入都具有唯一的id,这些id取自App组件中的对象。
轻微重构的机会
这里我们可以进行一点重构。与其在ToDoItem组件内生成复选框的id,我们可以将id转换为一个 prop。虽然这不是严格必要的,但它使我们更容易管理,因为无论如何我们都需要为每个待办事项创建一个唯一的id。
- 向您的
ToDoItem组件添加一个新的 prop——id。 - 使其成为必需的,并将其类型设置为
String。 - 为了防止名称冲突,请从您的
data属性中删除id字段。 - 您不再使用
nanoid,因此您需要删除import { nanoid } from 'nanoid';行,否则您的应用程序将抛出错误。
ToDoItem组件中的<script>内容现在应该如下所示:
export default {
props: {
label: { required: true, type: String },
done: { default: false, type: Boolean },
id: { required: true, type: String },
},
data() {
return {
isDone: this.done,
};
},
};
现在,在您的App.vue组件中,将item.id作为 prop 传递给ToDoItem组件。您的App.vue模板现在应该如下所示:
<template>
<div id="app">
<h1>My To-Do List</h1>
<ul>
<li v-for="item in ToDoItems" :key="item.id">
<to-do-item
:label="item.label"
:done="item.done"
:id="item.id"></to-do-item>
</li>
</ul>
</div>
</template>
当您查看渲染的站点时,它应该看起来相同,但是我们的重构现在意味着我们的id是从App.vue内部的数据中获取并作为 prop 传递到ToDoItem中,就像其他所有内容一样,因此现在事情变得更加逻辑和一致。