vue实训-学习计划表

作者:犯困乐 发布时间: 2026-05-09 阅读量:37 评论数:0

需求文档

第2章 阶段案例 开发文档(2).pdf

需求解析

  1. 使用 VSCode 打开项目目录
    D:\vue\chapter02\learning_schedule

  2. 清除默认样式
    删除 src\style.css 中的所有样式代码。

  3. 引入 Bootstrap
    在 index.html 中引入:

    html

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    
  4. 修改 App.vue 默认内容

    vue

    <template>
      学习计划表
    </template>
    

2.1.2 渲染表格区域数据

  1. 定义数据

    js

    import { ref } from 'vue'
    const list = ref([
      {
        id: '1',
        subject: 'Vue.js前端实战开发',
        content: '学习指令,例如v-if、v-for、v-model等',
        place: '自习室',
        status: false,
      }
    ])
    
  2. 表格结构
    使用 Bootstrap 的 table 样式类,包含:序号、学习科目、学习内容、学习地点、完成状态、操作列。

  3. 循环渲染与状态切换

    • 使用 v-for 渲染表格行,:key 绑定 item.id
    • 完成状态列使用 switch 开关样式,v-model 绑定 item.status
    • 通过 v-if / v-else 显示“已完成”或“未完成”。
    • “删除”按钮用于删除该行计划。

2.1.3 实现学习计划的删除功能

  1. 绑定点击事件

    html

    <a href="javascript:;" @click="remove(item.id, item.status)">删除</a>
    
  2. 实现删除方法

    js

    let remove = (id, status) => {
      if (status) {
        list.value = list.value.filter(item => item.id !== id)
      } else {
        alert('请完成该学习计划后再进行删除操作!')
      }
    }
    
    • 只有完成状态为“已完成”(status === true)时才能删除。

2.1.4 实现学习计划的添加功能

  1. 定义表单相关数据

    js

    let subject = ref('')
    let content = ref('')
    let nextId = ref('')
    let selectedOption = ref('自习室')
    let options = ref([
      { placeCode: 0, place: '自习室' },
      { placeCode: 1, place: '图书馆' },
      { placeCode: 2, place: '宿舍' }
    ])
    
  2. 卡片区域结构

    • 卡片标题:学习计划表
    • 表单包含:学习科目(文本框)、学习内容(多行文本框)、学习地点(下拉框)、添加按钮。
  3. 表单控件绑定与修饰符

    • 使用 v-model.trim 绑定输入值,自动去除首尾空格。
    • 下拉框 v-model 绑定 selectedOption,选项通过 v-for 动态渲染。
  4. 表单提交事件

    html

    <form @submit.prevent="add">
    
  5. 添加方法实现

    js

    let add = () => {
      if (subject.value === '') {
        alert('学习科目为必填项!')
        return
      }
      nextId.value = Math.max(...list.value.map(item => item.id)) + 1
      const obj = {
        id: nextId.value,
        subject: subject.value,
        content: content.value,
        place: selectedOption.value,
        status: false,
      }
      list.value.push(obj)
      subject.value = ''
      content.value = ''
      selectedOption.value = '自习室'
    }
    

2.1.5 实现状态的切换功能

  • 问题:点击 <label> 文字时无法切换对应行的完成状态。

  • 解决:动态生成 id 和 for 属性,关联 input 与 label

    html

    <input :id="'cb' + item.id" v-model="item.status" ... />
    <label :for="'cb' + item.id" v-if="item.status">已完成</label>
    <label :for="'cb' + item.id" v-else>未完成</label>
    

总结

本案例实现了一个基于 Vue 3 + Bootstrap 的“学习计划表”应用,涵盖以下功能:

  • 表格数据的动态渲染
  • 学习计划的新增与删除
  • 完成状态的切换与样式联动
  • 表单输入的双向绑定与修饰符使用

通过该案例,实践了 v-forv-ifv-model、事件绑定、修饰符等 Vue 核心指令与功能。

最后代码

首先要在index.html中引入以下样式资源

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script setup>
import { ref } from 'vue'

const list = ref([
  {
    id: '1',
    subject: 'Vue.js前端实战开发',
    content: '学习指令,例如v-if、v-for、v-model等',
    place: '自习室',
    status: false,
  }
])

const subject = ref('')
const content = ref('')
const nextId = ref('')
const selectedOption = ref('自习室')
const options = ref([
  { placeCode: 0, place: '自习室' },
  { placeCode: 1, place: '图书馆' },
  { placeCode: 2, place: '宿舍' }
])

const remove = (id, status) => {
  if (status) {
    list.value = list.value.filter(item => item.id !== id)
  } else {
    alert('请完成该学习计划后再进行删除操作!')
  }
}

const add = () => {
  if (subject.value === '') {
    alert('学习科目为必填项!')
    return
  }
  const maxId = list.value.length > 0 ? Math.max(...list.value.map(item => Number(item.id))) : 0
  nextId.value = maxId + 1
  const obj = {
    id: nextId.value.toString(),
    subject: subject.value,
    content: content.value,
    place: selectedOption.value,
    status: false,
  }
  list.value.push(obj)
  subject.value = ''
  content.value = ''
  selectedOption.value = '自习室'
}
</script>

<template>
  <div class="container mt-4">
    <div class="card">
      <div class="card-header">
        <h5>学习计划表</h5>
      </div>
      <div class="card-body">
        <form @submit.prevent="add" class="mb-4">
          <div class="row g-3">
            <div class="col-md-3">
              <input type="text" class="form-control" v-model.trim="subject" placeholder="学习科目">
            </div>
            <div class="col-md-5">
              <textarea class="form-control" v-model.trim="content" placeholder="学习内容" rows="1"></textarea>
            </div>
            <div class="col-md-2">
              <select class="form-select" v-model="selectedOption">
                <option v-for="option in options" :key="option.placeCode" :value="option.place">{{ option.place }}</option>
              </select>
            </div>
            <div class="col-md-2">
              <button type="submit" class="btn btn-primary w-100">添加</button>
            </div>
          </div>
        </form>

        <table class="table table-bordered table-hover">
          <thead class="table-light">
            <tr>
              <th>序号</th>
              <th>学习科目</th>
              <th>学习内容</th>
              <th>学习地点</th>
              <th>完成状态</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(item, index) in list" :key="item.id">
              <td>{{ index + 1 }}</td>
              <td>{{ item.subject }}</td>
              <td>{{ item.content }}</td>
              <td>{{ item.place }}</td>
              <td>
                <div class="form-check form-switch">
                  <input class="form-check-input" type="checkbox" :id="'cb' + item.id" v-model="item.status">
                  <label class="form-check-label" :for="'cb' + item.id" v-if="item.status">已完成</label>
                  <label class="form-check-label" :for="'cb' + item.id" v-else>未完成</label>
                </div>
              </td>
              <td>
                <a href="javascript:;" class="text-danger" @click="remove(item.id, item.status)">删除</a>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </div>
</template>

评论