第5章 5.1 组件库:Element Plus 入门
🎯 开场:为什么你的页面写得像「毛坯房」?
上一章我们做完电商首页和详情页,有没有这种感觉:页面能跑,但怎么看怎么丑。按钮灰突突的,表格歪歪扭扭,输入框没有任何交互反馈……
这就是「自己造轮子」的代价。
就好比你装修房子,地板要自己浇筑、门要自己钉、灯要自己焊——不是不行,是没必要。把时间花在「为什么非得自己造门」这件事上,性价比太低了。
痛点来了:
- 想做个好看的表格?得写几百行 CSS,还不一定对齐
- 想做个表单验证?自己写逻辑能写到怀疑人生
- 想做个加载状态、弹窗、通知?来来来,从头造
学完这章你能解决: 用 Element Plus 这个现成的「装修队」,让页面从「毛坯房」直接进化到「精装房」,而且代码量少到你不敢相信。
🧱 基础:Element Plus 到底是什么?
5.1.1 先说人话:Element Plus 是什么?
如果说 Vue 3 是一套「毛坯房建筑图纸」,那 Element Plus 就是\n\n
\n\n
\n\n「精装房装修套餐」——里面包含了各种现成的组件:按钮、表单、表格、弹窗、导航栏……你只需要「组装」就行。
类比 Python 的世界:如果 requests 库让「发 HTTP 请求」变得简单,那 Element Plus 就是让「写后台管理页面」变得简单。
5.1.2 安装 Element Plus(2 分钟)
首先,我们要在项目里「引入装修队」:
npm install element-plus
然后在 main.ts 里引入(如果你用的是 Vite 项目):
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' // 引入样式
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus) // 注册 Element Plus
app.mount('#app')
这 3 行代码,就是在告诉 Vue:「我请了一个装修队,后续页面装修就靠它了」。
5.1.3 第一个组件:Button 按钮
装修队进场,先装个「门把手」试试——哦不对,先放个按钮:
<template>
<div>
<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>
</div>
</template>
<script setup lang="ts">
// 不需要写任何 JS,el-button 是自带的组件
</script>
这行在干嘛: <el-button> 就是 Element Plus 提供的「按钮组件」,type 属性控制颜色风格,不用写一行 CSS。
运行后你得到 5 个配色好看的按钮:蓝色是「主要」,绿色是「成功」,橙色是「警告」,红色是「危险」。一个 CSS 都没写。
5.1.4 Table 表格:数据展示神器
电商后台最常见的就是「表格」——订单列表、用户列表、商品列表。传统方式要自己画表格、对齐表头、处理分页……Element Plus 一行搞定:
<template>
<el-table :data="products" stripe border style="width: 100%">
<el-table-column prop="name" label="商品名称" width="200" />
<el-table-column prop="price" label="价格" width="120" />
<el-table-column prop="stock" label="库存" width="100" />
<el-table-column label="操作">
<template #default="scope">
<el-button size="small" @click="handleEdit(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 商品数据
const products = ref([
{ name: 'iPhone 15', price: 6999, stock: 100 },
{ name: 'MacBook Pro', price: 12999, stock: 50 },
{ name: 'AirPods Pro', price: 1899, stock: 200 },
])
// 编辑操作
const handleEdit = (row: any) => {
console.log('编辑商品:', row.name)
}
// 删除操作
const handleDelete = (row: any) => {
console.log('删除商品:', row.name)
}
</script>
这行在干嘛:
- :data="products" 绑定数据源(就像给表格喂数据)
- prop="name" 指定显示哪一列
- #default="scope" 是插槽,用来放自定义内容(比如操作按钮)
stripe 让表格行交替变色(斑马纹),border 加上边框线——这两个属性就是「好看」的秘密。
5.1.5 Form 表单:数据录入必备
用户注册、商品上架……都离不开表单。Element Plus 的表单组件支持「数据绑定 + 验证」一条龙:
<template>
<el-form :model="form" :rules="rules" label-width="100px">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="form.password" type="password" placeholder="请输入密码" show-password />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm">提交</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { ElMessage } from 'element-plus'
// 表单数据
const form = reactive({
username: '',
email: '',
password: '',
})
// 验证规则
const rules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 10, message: '用户名3-10个字符', trigger: 'blur' },
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' },
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, message: '密码至少6位', trigger: 'blur' },
],
}
// 提交表单
const submitForm = () => {
console.log('表单数据:', form)
ElMessage.success('提交成功!')
}
// 重置表单
const resetForm = () => {
form.username = ''
form.email = ''
form.password = ''
}
</script>
这行在干嘛:
- :model="form" 绑定表单数据(双向绑定)
- :rules="rules" 绑定验证规则
- prop="username" 关联验证规则和表单项
- ElMessage.success() 是 Element Plus 的「轻提示」,类似 Python 的 print() 但更好看
验证规则里的 required: true、min: 3、type: 'email' 都是「开箱即用」的验证器,自己写?光邮箱正则就能折腾半天。
🔥 实战:3 个项目练手感
项目 1:5 分钟搞定「商品管理列表」
目标: 做一个能展示商品、能编辑删除的列表页。
<template>
<div style="padding: 20px;">
<h2>📦 商品管理</h2>
<!-- 表格区域 -->
<el-table :data="products" stripe border style="width: 100%; margin-top: 20px;">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="name" label="商品名称" />
<el-table-column prop="category" label="分类" width="120" />
<el-table-column prop="price" label="价格" width="100" />
<el-table-column prop="stock" label="库存" width="100" />
<el-table-column label="操作" width="180">
<template #default="scope">
<el-button size="small" type="primary" @click="editProduct(scope.row)">编辑</el-button>
<el-button size="small" type="danger" @click="deleteProduct(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 编辑弹窗 -->
<el-dialog v-model="dialogVisible" title="编辑商品" width="500px">
<el-form :model="editForm" label-width="80px">
<el-form-item label="商品名称">
<el-input v-model="editForm.name" />
</el-form-item>
<el-form-item label="价格">
<el-input-number v-model="editForm.price" :min="0" />
</el-form-item>
<el-form-item label="库存">
<el-input-number v-model="editForm.stock" :min="0" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirmEdit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
// 商品数据
const products = ref([
{ id: 1, name: 'iPhone 15', category: '手机', price: 6999, stock: 100 },
{ id: 2, name: 'MacBook Pro', category: '电脑', price: 12999, stock: 50 },
{ id: 3, name: 'AirPods Pro', category: '配件', price: 1899, stock: 200 },
])
// 编辑弹窗相关
const dialogVisible = ref(false)
const editForm = reactive({
id: 0,
name: '',
price: 0,
stock: 0,
})
// 编辑商品
const editProduct = (row: any) => {
editForm.id = row.id
editForm.name = row.name
editForm.price = row.price
editForm.stock = row.stock
dialogVisible.value = true
}
// 确认编辑
const confirmEdit = () => {
const product = products.value.find(p => p.id === editForm.id)
if (product) {
product.name = editForm.name
product.price = editForm.price
product.stock = editForm.stock
ElMessage.success('修改成功')
}
dialogVisible.value = false
}
// 删除商品
const deleteProduct = async (row: any) => {
try {
await ElMessageBox.confirm('确定要删除这个商品吗?', '提示', {
type: 'warning',
})
const index = products.value.findIndex(p => p.id === row.id)
if (index > -1) {
products.value.splice(index, 1)
ElMessage.success('删除成功')
}
} catch {
// 用户取消
}
}
</script>
预期输出: 页面显示一个表格,有 3 条商品数据,每行有「编辑」和「删除」按钮。点击编辑会弹出对话框,删除会弹出确认框。
一句话解释: 这个项目把 Table + Dialog + MessageBox 组合起来,实现了「增删改查」的演示。真实项目中,数据会从后端 API 获取,下一章我们会讲到。
项目 2:15 分钟搞定「用户注册表单页」
目标: 做一个带完整验证的注册表单,支持密码确认、昵称选择、用户协议勾选。
<template>
<div class="register-container">
<el-card class="register-card">
<template #header>
<div class="card-header">
<span>👤 用户注册</span>
</div>
</template>
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
status-icon
>
<!-- 用户名 -->
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="3-10位字母或数字" />
</el-form-item>
<!-- 邮箱 -->
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="用于找回密码" />
</el-form-item>
<!-- 密码 -->
<el-form-item label="密码" prop="password">
<el-input v-model="form.password" type="password" placeholder="至少6位" show-password />
</el-form-item>
<!-- 确认密码 -->
<el-form-item label="确认密码" prop="confirmPassword">
<el-input v-model="form.confirmPassword" type="password" placeholder="再输入一次" show-password />
</el-form-item>
<!-- 性别 -->
<el-form-item label="性别" prop="gender">
<el-radio-group v-model="form.gender">
<el-radio label="male">男</el-radio>
<el-radio label="female">女</el-radio>
<el-radio label="other">保密</el-radio>
</el-radio-group>
</el-form-item>
<!-- 年龄段 -->
<el-form-item label="年龄段" prop="ageGroup">
<el-select v-model="form.ageGroup" placeholder="请选择">
<el-option label="18岁以下" value="under18" />
<el-option label="18-25岁" value="18-25" />
<el-option label="26-35岁" value="26-35" />
<el-option label="35岁以上" value="above35" />
</el-select>
</el-form-item>
<!-- 用户协议 -->
<el-form-item prop="agreement">
<el-checkbox v-model="form.agreement">
我已阅读并同意<a href="#" style="color: #409eff;">《用户协议》</a>
</el-checkbox>
</el-form-item>
<!-- 提交按钮 -->
<el-form-item>
<el-button type="primary" style="width: 100%;" @click="submitForm">
注册
</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
// 表单引用
const formRef = ref<FormInstance>()
// 表单数据
const form = reactive({
username: '',
email: '',
password: '',
confirmPassword: '',
gender: '',
ageGroup: '',
agreement: false,
})
// 自定义验证:确认密码
const validateConfirmPassword = (rule: any, value: any, callback: any) => {
if (value !== form.password) {
callback(new Error('两次输入的密码不一致'))
} else {
callback()
}
}
// 验证规则
const rules: FormRules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ pattern: /^[a-zA-Z0-9]{3,10}$/, message: '3-10位字母或数字', trigger: 'blur' },
],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' },
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, message: '密码至少6位', trigger: 'blur' },
],
confirmPassword: [
{ required: true, message: '请确认密码', trigger: 'blur' },
{ validator: validateConfirmPassword, trigger: 'blur' },
],
gender: [
{ required: true, message: '请选择性别', trigger: 'change' },
],
ageGroup: [
{ required: true, message: '请选择年龄段', trigger: 'change' },
],
agreement: [
{ validator: (rule, value, callback) => {
value ? callback() : callback(new Error('请勾选用户协议'))
}, trigger: 'change' },
],
}
// 提交表单
const submitForm = async () => {
if (!formRef.value) return
await formRef.value.validate((valid) => {
if (valid) {
console.log('注册数据:', form)
ElMessage.success('注册成功!即将跳转到登录页...')
} else {
ElMessage.error('请检查表单填写是否正确')
}
})
}
</script>
<style scoped>
.register-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #f0f2f5;
}
.register-card {
width: 500px;
}
.card-header {
font-size: 18px;
font-weight: bold;
}
</style>
预期输出: 一个居中的注册卡片,包含用户名、邮箱、密码、确认密码(带一致性验证)、性别单选、年龄段下拉选择、协议勾选。填写错误会有红色提示,填写正确点击注册显示成功消息。
一句话解释: 这个项目展示了 Form 的完整能力:多种输入组件(Input/Select/Radio/Checkbox)、内置验证规则、自定义验证函数(密码一致性)、以及提交时的整体验证。
项目 3:15 分钟搞定「仪表盘首页」
目标: 把前两个项目的组件组合起来,做一个电商后台的仪表盘首页。
<template>
<div class="dashboard">
<!-- 顶部导航 -->
<el-menu mode="horizontal" :default-active="activeMenu" class="top-menu">
<el-menu-item index="1">📊 数据概览</el-menu-item>
<el-menu-item index="2">📦 商品管理</el-menu-item>
<el-menu-item index="3">👥 用户管理</el-menu-item>
<el-menu-item index="4">📝 订单管理</el-menu-item>
</el-menu>
<!-- 统计卡片 -->
<el-row :gutter="20" style="margin: 20px 0;">
<el-col :span="6">
<el-card shadow="hover">
<div class="stat-card">
<div class="stat-value">¥ 128,399</div>
<div class="stat-label">今日销售额</div>
<el-tag type="success" size="small">+12.5% ↑</el-tag>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<div class="stat-card">
<div class="stat-value">1,234</div>
<div class="stat-label">今日订单</div>
<el-tag type="success" size="small">+8.2% ↑</el-tag>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<div class="stat-card">
<div class="stat-value">89</div>
<div class="stat-label">待发货</div>
<el-tag type="warning" size="small">需处理</el-tag>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<div class="stat-card">
<div class="stat-value">3.2%</div>
<div class="stat-label">退货率</div>
<el-tag type="danger" size="small">-0.5% ↓</el-tag>
</div>
</el-card>
</el-col>
</el-row>
<!-- 最新订单列表 -->
<el-card style="margin: 0 20px;">
<template #header>
<div class="card-header">
<span>📋 最新订单</span>
<el-button type="primary" size="small" text>查看全部</el-button>
</div>
</template>
<el-table :data="recentOrders" stripe>
<el-table-column prop="orderId" label="订单号" width="150" />
<el-table-column prop="customer" label="客户" width="120" />
<el-table-column prop="product" label="商品" />
<el-table-column prop="amount" label="金额" width="100">
<template #default="scope">
¥{{ scope.row.amount.toFixed(2) }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100">
<template #default="scope">
<el-tag :type="getStatusType(scope.row.status)">
{{ scope.row.statusText }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="下单时间" width="180" />
</el-table>
</el-card>
<!-- 消息通知 -->
<el-card style="margin: 20px;">
<template #header>
<span>🔔 系统通知</span>
</template>
<el-empty v-if="notifications.length === 0" description="暂无新通知" />
<el-list v-else>
<el-list-item v-for="item in notifications" :key="item.id">
<el-badge :value="item.new ? '新' : ''" :hidden="!item.new">
<span>{{ item.content }}</span>
</el-badge>
</el-list-item>
</el-list>
</el-card>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 当前激活的菜单
const activeMenu = ref('1')
// 最新订单数据
const recentOrders = ref([
{ orderId: 'DD20240101001', customer: '张三', product: 'iPhone 15', amount: 6999, status: 'pending', statusText: '待发货', createTime: '2024-01-15 10:30:22' },
{ orderId: 'DD20240101002', customer: '李四', product: 'MacBook Pro', amount: 12999, status: 'shipped', statusText: '已发货', createTime: '2024-01-15 11:15:08' },
{ orderId: 'DD20240101003', customer: '王五', product: 'AirPods Pro', amount: 1899, status: 'completed', statusText: '已完成', createTime: '2024-01-15 14:22:45' },
{ orderId: 'DD20240101004', customer: '赵六', product: 'iPad Air', amount: 4399, status: 'pending', statusText: '待发货', createTime: '2024-01-15 16:05:33' },
])
// 系统通知
const notifications = ref([
{ id: 1, content: '您有 3 个订单等待发货处理', new: true },
{ id: 2, content: '商品「iPhone 15」库存不足,请及时补货', new: true },
{ id: 3, content: '系统将于今晚 23:00 进行维护升级', new: false },
])
// 获取状态标签类型
const getStatusType = (status: string) => {
const typeMap: Record<string, any> = {
pending: 'warning',
shipped: 'primary',
completed: 'success',
cancelled: 'info',
}
return typeMap[status] || 'info'
}
</script>
<style scoped>
.dashboard {
background: #f5f7fa;
min-height: 100vh;
}
.top-menu {
padding: 0 20px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.stat-card {
text-align: center;
padding: 10px 0;
}
.stat-value {
font-size: 28px;
font-weight: bold;
color: #303133;
margin-bottom: 8px;
}
.stat-label {
font-size: 14px;
color: #909399;
margin-bottom: 8px;
}
</style>
预期输出: 一个完整的仪表盘页面,包含顶部导航、4 个统计卡片(销售额/订单数/待发货/退货率)、最新订单表格(带状态标签)、系统通知列表。
一句话解释: 这个项目展示了 Element Plus 的「组合能力」——Menu、Row/Col(栅格布局)、Card、Tag、Badge、Empty 等组件组合在一起,形成了看起来很专业的后台首页。
💪 进阶:5 个新人必踩的坑
坑 1:表格数据变了,但页面没更新
❌ 错误写法:
const products = [
{ name: 'iPhone', price: 6999 },
]
// 直接修改数组,Vue 检测不到
products[0].price = 5999 // 页面不会更新!
✅ 正确写法:
import { ref } from 'vue'
const products = ref([
{ name: 'iPhone', price: 6999 },
])
// 通过 .value 修改,Vue 能检测到
products.value[0].price = 5999 // 页面更新了
原因: Element Plus 的 :data 绑定的是响应式数据(ref 或 reactive),普通数组不是响应式的。
坑 2:Dialog 弹窗关闭后,数据还残留
❌ 错误写法:
const dialogVisible = ref(false)
const editForm = reactive({ name: '', price: 0 })
const openDialog = () => {
dialogVisible.value = true
// 没清空 editForm,上次数据会残留
}
✅ 正确写法:
const dialogVisible = ref(false)
const editForm = reactive({ id: 0, name: '', price: 0 })
const openDialog = (row) => {
dialogVisible.value = true
// 打开前先重置数据
Object.assign(editForm, { id: row.id, name: row.name, price: row.price })
}
const closeDialog = () => {
dialogVisible.value = false
// 关闭后清空表单
editForm.id = 0
editForm.name = ''
editForm.price = 0
}
坑 3:表单验证不触发
❌ 错误写法:
<el-form :model="form" :rules="rules">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" />
</el-form-item>
<!-- 缺少 ref -->
</el-form>
✅ 正确写法:
<template>
<el-form ref="formRef" :model="form" :rules="rules">
<!-- 表单内容 -->
</el-form>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { FormInstance } from 'element-plus'
const formRef = ref<FormInstance>() // 一定要定义这个 ref
const submit = async () => {
await formRef.value?.validate() // 调用 validate 方法
}
</script>
原因: :rules 只是声明规则,实际验证需要通过 formRef.value.validate() 手动触发。
坑 4:DatePicker 返回的格式不对
❌ 错误做法:
const handleDateChange = (date) => {
console.log(date) // 打印出来是 Date 对象,不是字符串
// 直接传给后端可能报错
}
✅ 正确做法:
<el-date-picker
v-model="form.date"
type="date"
placeholder="选择日期"
format="YYYY-MM-DD" // 格式化显示
value-format="YYYY-MM-DD" // 格式化值
/>
原因: DatePicker 的 value-format 属性控制绑定的值是什么格式,不设置的话默认是 Date 对象。
坑 5:Select 多选模式下值是数组但验证写错了
❌ 错误写法:
const rules = {
tags: [{ required: true, message: '请选择标签', trigger: 'change' }],
}
// 多选时,form.tags 是数组 [],required: true 对空数组会失效
✅ 正确写法:
const rules = {
tags: [
{ required: true, message: '请选择标签', trigger: 'change' },
{ type: 'array', min: 1, message: '至少选择一个标签', trigger: 'change' },
],
}
调试技巧:如何排查 Element Plus 组件问题?
当你发现组件表现不符合预期时,可以这样做:
1. 检查数据绑定是否正确:
<el-input v-model="form.name" />
<!-- 疑难杂症时,加个隐藏的调试输出 -->
<pre>{{ JSON.stringify(form, null, 2) }}</pre>
2. 使用 Element Plus 官方调试工具:
浏览器安装「Vue DevTools」插件,选择「Element Plus」标签页,可以看到每个组件的内部状态。
3. 查看官方文档的「 playground」:
Element Plus 官网每个组件都有在线示例,直接复制下来改一改就能用。
✏️ 练习题
练习 1(2 分钟):换个图标按钮
- 输入:在项目 1 的表格里,把「编辑」按钮改成 type="warning"
- 预期输出:按钮变成橙色
- 提示:按钮的 type 属性控制颜色
练习 2(3 分钟):给表格加一列
- 输入:在项目 1 的商品表格里,加一列「分类」,数据为 { category: '手机' }
- 预期输出:表格多出一列「分类」
- 提示:参考现有的 el-table-column 写法
练习 3(5 分钟):添加邮箱验证
- 输入:在项目 2 的表单里,把「邮箱」字段的验证规则改成 type: 'email'
- 预期输出:输入非邮箱格式会提示「邮箱格式不正确」
- 提示:Element Plus 内置了 type: 'email' 验证器
练习 4(8 分钟):把项目 1 和项目 2 串起来
- 输入:在项目 1 的「编辑」弹窗里,加入用户名和邮箱两个字段,并添加验证
- 预期输出:编辑弹窗打开时能修改用户名和邮箱,点击确定时验证通过才关闭
- 提示:参考项目 2 的表单验证写法
练习 5(5 分钟):分析这个报错
- 输入:报错信息是 TypeError: Cannot read properties of undefined (reading 'validate')
- 预期输出:说出原因并修复
- 提示:检查 formRef 是否正确定义和关联
作业:做一个「任务管理仪表盘」
- 需求描述: 做一个团队任务管理的小工具,用来查看和跟踪任务进度
- 功能点:
1. 顶部导航栏(首页/任务列表/成员管理)
2. 4 个统计卡片(总任务/进行中/已完成/已逾期)
3. 任务表格(任务名/负责人/状态/截止日期),状态用 Tag 显示
4. 点击「标记完成」按钮,任务状态变化 - 加分项:
1. 给表格加上「截止日期」排序
2. 用el-date-picker筛选特定日期范围的任务 - 验收标准: 能跑起来 + 表格能显示数据 + 点击按钮状态会变化
- 提交方式: 评论区贴代码或 GitHub 链接
📚 总结
本文学到的 3 个核心点:
- Element Plus 是 Vue 3 的「精装房套餐」——各种 UI 组件开箱即用,不用自己造轮子
- Table + Form 是后台系统的两大核心——表格展示数据,表单录入数据,两者都支持数据验证
- 响应式是 Vue 的精髓——数据变了页面才会变,用
ref/reactive包装数据是基本功
延伸学习资源:
- Element Plus 官方文档(每个组件都有完整示例)
- Vue 3 官方文档(深入理解响应式原理)
- 《Vue.js 设计与实现》(深入 Vue 3 源码)
互动钩子: 你在写后台页面时,最头疼的是哪个部分?是表格复杂的筛选排序,还是表单的各种验证规则?评论区聊聊,老粉优先回复!
下一章我们要聊的是「移动端」的 UI 库——如果你觉得 Element Plus 是给 PC 端用的,那下一章的 Vant 就是移动端的 Element Plus,专门解决「手机网页怎么做才好看」这个问题。敬请期待!

评论(0)