1
2.1 案例——学习计划表
2.1.1 准备工作
在开发“学习计划表”案例之前,需要先完成一些准备工作,具体步骤如下。
① 打开命令提示符,切换到 D:\vue\chapter02 目录,在该目录下执行如下命令,创建
项目。
npm create vite@4.1.0 learning_schedule -- --template vue
项目创建完成后,执行如下命令进入项目目录,启动项目。
cd learning_schedule
npm install
npm run dev
项目启动后,可以使用 URL 地址 http://127.0.0.1:5173/ 进行访问。
② 使用 VS Code 编辑器打开 D:\vue\chapter02\learning_schedule 目录。
③ 将 src\style.css 文件中的样式代码全部删除,从而避免项目创建时自带的样式代码
影响本案例的实现效果。
④ 打开 D:\vue\chapter02\ learning_schedule 目录,找到 index.html 文件。在文件中引
入 BootStrap 样式文件,具体代码如下。
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 ……(原有代码)
5 <link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.c
ss" rel="stylesheet">
6 </head>
7 </html>
上述代码中,第 5 行代码引入 Bootstrap 的 CSS 文件,引用后即可使用 Bootstrap 快速
开发响应式网页,使用全局 CSS 样式美化标签。
⑤ 修改 src\App.vue 文件中的默认内容,具体代码如下。
1 <template>
2 学习计划表
3 </template>
至此,“学习计划表”案例准备工作已完成。 2
2.1.2 渲染表格区域数据
接下来正式进入“学习计划表”案例的开发。在 App 组件中编写表格区域的页面结
构和样式,并在页面上渲染表格数据,具体实现步骤如下。
① 在 <script setup> 标签中定义渲染表格所需的数据,具体代码如下。
1 <script setup>
2 import { ref } from 'vue'
3 const list = ref([
4 {
5 id: '1',
6 subject: 'Vue.js 前端实战开发 ',
7 content: ' 学习指令,例如 v-if 、 v-for 、 v-model 等 ',
8 place: ' 自习室 ',
9 status: false,
10 },
11 ])
12 </script>
上述代码中, list 数组表示渲染表格区域所需的数据, id 属性表示序号, subject 属性
表示学习科目, content 属性表示学习内容, place 属性表示学习地点, status 属性表示学
习计划的完成状态,若属性值为 false ,表示“未完成”,若属性值为 true 表示“已完
成”。
② 根据 Bootstrap 文档找到 Tables ,根据实际需要合适的样式,本案例中表格的结
构样式具体如下。
1 <template>
2 <table class="table table-striped table-hover table-bordered">
3 <thead>
4 <tr>
5 <th scope="col"> 序号 </th>
6 <th scope="col"> 学习科目 </th>
7 <th scope="col"> 学习内容 </th>
8 <th scope="col"> 学习地点 </th>
9 <th scope="col"> 完成状态 </th>
10 <th scope="col"> 操作 </th>
11 </tr>
12 </thead>
13 <tbody>
14 <tr> 3
15 <td> 序号 </td>
16 <td> 学习科目 </td>
17 <td> 学习内容 </td>
18 <td> 学习地点 </td>
19 <td> 完成状态 </td>
20 <td> 操作 </td>
21 </tr>
22 </tbody>
23 </table>
24 </template>
保存上述代码后,在浏览器中打开 http://127.0.0.1:5173/ ,初始页面如图 2-1 所示。
图 2-1
初始页面
③ 接下来通过 v-for 指令循环渲染表格行的数据,修改 <tbody> 标签中的代码,具
体如下。
1 <tbody>
2 <tr v-for="item in list" :key="item.id" >
3 <td>{{ item.id }}</td>
4 <td>{{ item.subject }}</td>
5 <td>{{ item.content }}</td>
6 <td>{{ item.place }}</td>
7 <td>
8 <div class="form-check form-switch">
9 <input class="form-check-input" type="checkbox" role="switch"
id="flexSwitchCheckDefault" v-model="item.status" />
10 <label class="form-check-label" for="flexSwitchCheckDefault" v
if="item.status"> 已完成 </label>
11 <label class="form-check-label" for="flexSwitchCheckDefault" v
else> 未完成 </label>
12 </div>
13 </td>
14 <td>
15 <a href="javascript:;"> 删除 </a> 4
16 </td>
17 </tr>
18 </tbody>
上述代码中,第 2~17 行代码通过 v-for 指令渲染表格行,将 list 数组中的数据渲染到
页面上,每项必须提供一个唯一 key 值;第 3~6 行代码将列表项中序号、学习科目、学
习内容、学习地点通过 Mustache 语法渲染到页面上;第 7~13 行代码将表格行渲染为
switch 开关效果,其中,第 8 行代码将 <input> 标签渲染为开关的效果,通过 v-model 指令
绑定绑定 data 中的 list 数组中每个对象的 status 属性,第 10~11 行代码通过 v-if 、 v-else
条件渲染指令根据 status 属性的属性值渲染“已完成”或“未完成”的 <label> 标签;第
15 行代码定义了 <a> 标签,通过单击删除字段,即可将该行学习计划删除。
保存上述代码后,在浏览器中打开 http://127.0.0.1:5173/ ,渲染表格数据的页面效果
如图 2-2 所示。
图 2-2
渲染表格数据的页面效果
从图 2-2 中可以看出,学习计划列表中的数据被成功渲染。
至此,学习计划表渲染表格区域数据已实现。
2.1.3 实现学习计划的删除功能
在单击表格行最后一列“删除”时,可以对整行的学习计划进行删除操作。在实现
该功能时,在单击“删除”时,传递该行数据所对应的 id 属性,通过调用数组中的
filter() 方法实现数据的过滤。在删除学习计划时,如果完成状态为“未完成”时禁止删
除,完成状态为“已删除”时该学习计划可以进行删除操作。实现学习计划删除功能的
具体步骤如下。
① 修改 <a> 标签,添加单击事件,具体代码如下。
<a href="javascript:;" @click="remove(item.id) "> 删除 </a>
上述代码中,加粗代码为新增代码,为 <a> 标签绑定单击事件,并传递参数 id 。
② 在 <script setup> 标签中编写 remove() 方法,实现学习计划的删除,具体代码如
下。
1 let remove = id => {
2 list.value = list.value.filter(item => item.id !== id)
3 } 5
上述代码中,第 2 行代码通过调用 filter() 方法创建一个新数组,新数组为通过检查指
定 list 数组中符合条件的所有元素。
③ 修改 <a> 标签,在单击“删除”时传递该学习计划的完成状态,具体代码如下。
<a href="javascript:;" @click="remove(item.id, item.status )"> 删除 </a>
④ 修改 remove() 方法,实现对学习计划完成状态的判断,具体代码如下。
1 let remove = (id, status ) => {
2 if (status) {
3 list.value = list.value.filter(item => item.id !== id)
4 } else {
5 alert(' 请完成该学习计划后再进行删除操作! ')
6 }
7 }
上述代码中,通过 if 进行判断,若 status 为 true ,则执行第 3 行代码进行删除操作,
否则执行第 5 行代码,弹出警告。
保存上述代码后,在浏览器中打开 http://127.0.0.1:5173/ 进行测试。
至此,学习计划表的删除功能已实现。
2.1.4 实现学习计划的添加功能
接下来实现添加学习计划的功能,学生可以自主填写学习科目、学习内容和学习地
点。该功能通过表单来进行实现,在单击“添加”按钮时实现表单中所有信息的提交,
进行添加学习计划的操作。实现学习计划的添加功能具体实现步骤如下。
① 首先在 <script setup> 标签中定义页面所需的数据,具体代码如下。
1 let subject = ref('')
2 let content = ref('')
3 let nextId = ref('')
4 let selectedOption = ref(' 自习室 ')
5 let options = ref([
6 { placeCode: 0, place: ' 自习室 ', },
7 { placeCode: 1, place: ' 图书馆 ', },
8 { placeCode: 2, place: ' 宿舍 ', },
9 ])
上述代码中,第 1 行代码定义了 subject ,表示学习科目;第 2 行代码定义了 content ,
表示学习内容;第 3 行代码定义了 nextId ,表示新添加数据的 id ;第 4 行代码定义了默认
选中的学习地点;第 5~9 行代码定义了 options 数组,表示学习地点,其中 placeCode 属性
表示地点编号, place 属性表示地点名称。
② 卡片区域的整体页面结构,具体代码如下。 6
1 <template>
2 <div class="card">
3 <!-- 标题区域 -->
4 <div class="card-header"> 学习计划表 </div>
5 <!-- 提交区域 -->
6 <div class="card-body">
7 <form>
8 <div class="row g-4">
9 <!-- 学习科目 -->
10 <div class="col-auto"></div>
11 <!-- 学习任务 -->
12 <div class="col-auto"></div>
13 <!-- 学习地点 -->
14 <div class="col-auto"></div>
15 <!-- 添加按钮 -->
16 <div class="col-auto">
17 <button type="submit" class="btn btn-primary"> 添加 </button>
18 </div>
19 </div>
20 </form>
21 </div>
22 </div>
23 <table class="table table-striped table-hover table-bordered">
24 ……(原有代码)
25 </table>
26 </template>
上述代码中,第 2~22 行代码为新增代码,表示卡片区域。第 4 行代码定义了标题区
域,名称为“学习计划表”,第 7~20 行代码定义了表单区域,实现学习计划的添加功
能。第 10 、 12 、 14 行代码分别定义了学习科目、学习任务、学习地点区域,这 3 个区域
的实现在后续步骤中进行讲解。第 16~18 行代码中,定义了“添加”按钮, type 类型为
submit ,当单击该按钮时会触发 <form> 标签的 submit 事件提交表单信息。
③ 添加卡片区域中学习科目区域的页面结构,具体代码如下。
1 <div class="col-auto">
2 <div class="input-group mb-3">
3 <span class="input-group-text" id="basic-addon1"> 学习科目 </span>
4 <input type="text" class="form-control" placeholder=" 请输入学习科目 "
v-model.trim="subject" />
5 </div> 7
6 </div>
上述代码中,第 2~5 行代码定义了学习科目区域,通过 <input> 标签定义的文本框可
以输入学习科目,通过 v-model 指令,将 <input> 标签与 subject 实现数据的双向绑定,即
当更改文本框中的值时 subject 的值更改。同时为 v-model 指令添加了 trim 修饰符,用于
自动过滤用户输入的首尾空白字符。
④ 添加卡片区域中学习任务区域的页面结构,具体代码如下。
1 <div class="col-auto">
2 <div class="input-group mb-3">
3 <span class="input-group-text" id="basic-addon1"> 学习内容 </span>
4 <textarea class="form-control" v-model.trim="content" placeholder="
请输入学习内容 " :style="{ height: '32px' }"></textarea>
5 </div>
6 </div>
上述代码中,第 2~5 行代码定义了学习内容区域,通过 <textarea> 标签定义的多行文
本框可以输入学习内容,通过 v-model 指令与 content 绑定,实现视图与数据的双向绑
定。同时为 v-model 指令添加了 trim 修饰符,用于自动过滤用户输入的首尾空白字符。
⑤ 添加卡片区域中学习地点区域的页面结构,具体代码如下。
1 <div class="col-auto">
2 <div class="input-group mb-3">
3 <span class="input-group-text" id="basic-addon1"> 学习地点 </span>
4 <select class="form-select form-select-sm" v-model="selectedOption" >
5 <option v-for="option in
options" :value="option.place" :key="option.placeCode" >
6 {{ option.place }}
7 </option>
8 </select>
9 </div>
10 </div>
上述代码中,第 2~9 行代码定义了学习地点区域,其中,第 4~8 行代码通过 <select>
标签定义了下拉列表,通过 v-model 指令与 selectedOption 绑定,实现数据的双向绑定。
如果 v-model 指令的初始值不匹配任何一个选项, <select> 标签会渲染成未选择的状态,
所以 selectedOption 属性值为“自习室”,表示 <select> 标签的初始值为“自习室”,自习
室为下拉列表中定义的一个值。第 5~7 行代码通过 v-for 条件渲染指令实现学习地点的渲
染,当下拉列表中选项改变时, selectedOption 属性更改。
⑥ 为 <form> 标签添加 submit 事件,实现单击“添加”按钮时添加信息,具体代码
如下。
<form @submit.prevent="add" >
……(原有代码) 8
</form>
上述代码中,黑色加粗部分为新增代码,添加事件处理函数为 add() ,同时为 submit
事件添加事件修饰符 prevent ,用来阻止表单的默认提交行为。实现在单击按钮后提交表
单,执行 add() 方法。
⑦ 在 <script setup> 标签中编写 add() 方法,实现学习计划的添加,具体代码如下。
1 let add = () => {
2 if (subject.value === '') {
3 alert(' 学习科目为必填项! ')
4 return
5 }
6 nextId.value = Math.max(...list.value.map(item => item.id)) + 1
7 const obj = {
8 id: nextId.value,
9 subject: subject.value,
10 content: content.value,
11 place: selectedOption.value,
12 status: false,
13 }
14 list.value.push(obj)
15 subject.value = ''
16 content.value = ''
17 selectedOption.value = ' 自习室 '
18 }
上述代码中,第 2~5 行代码通过 if 进行判断,若学习科目字段 subject 为空,则弹出
提示,且不执行接下来的添加操作;第 6 行代码,通过调用 max() 方法,找到 list 数组中
id 中最大值,新添加数据的 id 为最大值加 1 ;第 7~13 行代码为需要新添加的数据,包括
id 、 subject 、 content 、 place 等,在默认情况下 status 为 false ,表示未完成该学习计划;第
14 行代码调用 push() 方法实现将 obj 对象添加到 list 数组的末尾;第 15~16 行代码将
subject 、 content 中的数据清空;第 17 行代码定义下拉列表的默认值。
保存上述代码后,在浏览器中打开 http://127.0.0.1:5173/ ,查看页面效果。
至此,学习计划表的添加功能已实现。
2.1.5 实现状态的切换功能
在实现学习计划的添加功能后,可以添加多条学习计划。在之前遗留如下问题:在表
格中更改添加后的几条学习计划的完成状态时,单击 <input> 标签生成的开关按钮可以实现 9
“未完成”与“已完成”状态之间的切换,但是单击 <label> 标签“未完成”与“已完成”
不能实现该表格行的完成状态的切换,只会切换表格第 1 行的完成状态。
若想实现单击文字也可实现某条学习计划完成状态的切换,则可以通过动态生成
<input> 标签的 id 属性,修改完成状态列的代码,具体如下。
1 <div class="form-check form-switch">
2 <input class="form-check-input" type="checkbox" role="switch" :id="'cb
' + item.id" v-model="item.status" />
3 <label class="form-check-label" :for="'cb' + item.id" v-if="item.statu
s"> 已完成 </label>
4 <label class="form-check-label" :for="'cb' + item.id" v-else> 未完成
</label>
5 </div>
上述代码中,黑体加粗部分代码为修改代码, <label> 标签中的 for 属性规定 <label> 标
签与哪个表单元素绑定,所以在第 3~3 行代码中通过 <label> 标签中 for 属性与 <input> 标签
绑定, for 属性的属性值为 <input> 标签的 id 属性值,实现单击 <label> 标签中的文本时,浏
览器自动将焦点转到和 <label> 标签的相关控件 <input> 控件中,实现单击文本完成某条学习
计划的完成状态的改变。
保存上述代码后,在浏览器中打开 http://127.0.0.1:5173/ 进行测试。
至此,“学习计划表”案例开发完成。