在前 4 课中,我们已经完成了多页面结构搭建(Vue Router)和全局数据管理(Pinia),但项目的数据仍存储在本地 ------ 实际开发中,应用的数据需要从后端服务器获取(比如从数据库读取待办、提交表单到服务器),且界面需要符合企业级美观标准。本节课将聚焦Axios(HTTP 请求工具) 和Element Plus(UI 组件库) 两大核心工具,解决 "前后端数据交互" 和 "快速搭建高质量界面" 的问题,让项目从 "本地演示应用" 升级为 "能对接真实后端的生产级应用"。
一、课前准备:安装 HTTP 请求与 UI 库依赖(5 分钟搞定)
本节课需要新增两个核心依赖:Axios(处理 HTTP 请求,对接后端接口)和Element Plus(Vue 3 官方推荐 UI 库,提供现成的美观组件),安装步骤简单,直接在现有项目中执行指令即可。
1. 安装依赖(终端执行)
确保当前处于my-first-vue-project项目目录下,打开 VS Code 终端,输入以下指令,依次安装:
bash
运行
# 安装Axios(HTTP请求工具,适配所有前端框架)
npm install axios
# 安装Element Plus(UI组件库,Vue 3专属)
npm install element-plus @element-plus/icons-vue
安装完成后,查看package.json文件,若出现axios、element-plus、@element-plus/icons-vue的版本信息,说明安装成功。
2. 课前知识铺垫(通俗理解核心工具)
- Axios:相当于前端和后端之间的 "信使"------ 前端通过 Axios 发送请求(比如 "获取待办数据""新增待办"),后端接收请求后处理数据(比如从数据库查询、存储),再通过 Axios 将结果返回给前端。支持 GET(查询)、POST(新增)、PUT(修改)、DELETE(删除)等常用请求方式,还能统一处理请求 / 响应拦截、错误提示,是企业开发中最常用的 HTTP 工具。
- Element Plus:相当于前端的 "组件超市"------ 提供了现成的按钮、输入框、卡片、弹窗、表格等美观组件,不用自己写复杂 CSS,直接调用组件就能快速搭建出和大厂 App 媲美的界面,还支持响应式适配(电脑、手机都能正常显示)。
二、核心实操一:Axios 入门 ------ 对接后端接口实现数据持久化
1. 步骤 1:配置 Axios 全局实例(统一管理请求规则)
在src文件夹下新建utils文件夹(专门存放工具类文件),创建axios.js文件,配置 Axios 全局实例(统一设置请求地址、超时时间、错误处理):
javascript
运行
// src/utils/axios.js
import axios from 'axios'
import { ElMessage } from 'element-plus' // 后续用于错误提示
// 创建Axios实例
const service = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com', // 免费测试接口地址(无需自己搭建后端)
timeout: 5000 // 请求超时时间(5秒没响应则报错)
})
// 请求拦截器:发送请求前做统一处理(比如添加token)
service.interceptors.request.use(
(config) => {
// 实际开发中可在此添加用户登录凭证(token),比如:
// config.headers['Authorization'] = localStorage.getItem('token')
return config
},
(error) => {
// 请求出错时的处理(比如网络错误)
ElMessage.error('请求发送失败,请检查网络!')
return Promise.reject(error)
}
)
// 响应拦截器:接收响应后做统一处理(比如错误提示、数据格式化)
service.interceptors.response.use(
(response) => {
// 只返回响应体中的data数据(简化后续使用)
return response.data
},
(error) => {
// 响应出错时的处理(比如接口返回404、500)
let errorMsg = '请求失败'
if (error.response) {
// 根据后端返回的错误状态码提示
switch (error.response.status) {
case 404:
errorMsg = '请求的接口不存在'
break
case 500:
errorMsg = '服务器内部错误'
break
default:
errorMsg = error.response.data.message || '请求失败'
}
}
ElMessage.error(errorMsg)
return Promise.reject(error)
}
)
export default service // 导出配置好的Axios实例
2. 步骤 2:创建 API 请求函数(统一管理接口)
在src文件夹下新建api文件夹(专门存放接口请求函数),创建todo.js文件,封装待办相关的接口请求(GET/POST/PUT/DELETE):
javascript
运行
// src/api/todo.js
import request from '../utils/axios'
// 接口说明:使用免费测试接口https://jsonplaceholder.typicode.com/todos
// 该接口返回模拟的待办数据,支持增删改查,虽为模拟接口,但语法和真实后端一致
// 1. 获取所有待办数据(GET请求)
export const getTodoList = () => {
return request({
url: '/todos', // 接口路径(拼接baseURL后完整地址:https://jsonplaceholder.typicode.com/todos)
method: 'GET'
})
}
// 2. 获取单个待办详情(GET请求,动态参数id)
export const getTodoDetail = (id) => {
return request({
url: `/todos/${id}`, // 动态路径:比如id=1时,路径为/todos/1
method: 'GET'
})
}
// 3. 新增待办(POST请求,传递待办数据)
export const addTodo = (todoData) => {
return request({
url: '/todos',
method: 'POST',
data: todoData // 传递给后端的参数(JSON格式)
})
}
// 4. 修改待办(PUT请求,传递修改后的数据)
export const updateTodo = (id, todoData) => {
return request({
url: `/todos/${id}`,
method: 'PUT',
data: todoData
})
}
// 5. 删除待办(DELETE请求)
export const deleteTodo = (id) => {
return request({
url: `/todos/${id}`,
method: 'DELETE'
})
}
3. 步骤 3:在 Pinia 中调用 API,替换本地数据
修改src/stores/todo.js,用接口请求替换之前的本地数据操作,实现数据持久化(从后端获取、提交到后端):
javascript
运行
// src/stores/todo.js
import { defineStore } from 'pinia'
import { getTodoList, addTodo, deleteTodo, updateTodo } from '../api/todo'
import { ElMessage } from 'element-plus'
export const useTodoStore = defineStore('todo', {
state: () => ({
todoList: [], // 初始化为空数组,从接口获取数据
loading: false // 加载状态(用于显示加载动画)
}),
actions: {
// 1. 从接口获取所有待办
async fetchTodoList() {
this.loading = true // 开始加载,显示动画
try {
const res = await getTodoList()
// 只取前10条数据(测试接口返回100条,简化展示)
this.todoList = res.slice(0, 10).map(item => ({
id: item.id,
title: item.title,
completed: item.completed
}))
} catch (error) {
this.todoList = [] // 请求失败时清空数据
ElMessage.error('获取待办列表失败!')
} finally {
this.loading = false // 加载结束,隐藏动画
}
},
// 2. 新增待办(提交到接口)
async addTodo(todoTitle) {
try {
const res = await addTodo({
title: todoTitle,
completed: false,
userId: 1 // 测试接口必填参数,固定值即可
})
// 新增成功后,将返回的新待办添加到本地列表(同步接口数据)
this.todoList.unshift({
id: res.id,
title: res.title,
completed: res.completed
})
ElMessage.success('新增待办成功!')
} catch (error) {
ElMessage.error('新增待办失败!')
}
},
// 3. 删除待办(调用接口删除)
async deleteTodo(id) {
try {
await deleteTodo(id)
// 删除成功后,同步更新本地列表
this.todoList = this.todoList.filter(item => item.id !== id)
ElMessage.success('删除待办成功!')
} catch (error) {
ElMessage.error('删除待办失败!')
}
},
// 4. 修改待办状态(完成/未完成)
async updateTodoStatus(id, completed) {
try {
await updateTodo(id, {
completed: completed
})
// 修改成功后,同步更新本地列表
const todoItem = this.todoList.find(item => item.id === id)
if (todoItem) {
todoItem.completed = completed
}
ElMessage.success(`待办已${completed ? '完成' : '取消完成'}!`)
} catch (error) {
ElMessage.error('修改待办状态失败!')
}
}
},
getters: {
todoCount() {
return this.todoList.length
},
completedCount() {
return this.todoList.filter(item => item.completed).length
}
}
})
4. Axios 核心功能实操验证
(1)获取接口数据
修改TodoList.vue,在页面加载时调用fetchTodoList获取接口数据:
vue
<script setup>
import { onMounted } from 'vue'
import { useTodoStore } from '../stores/todo'
const todoStore = useTodoStore()
// 页面加载时获取待办列表
onMounted(() => {
todoStore.fetchTodoList()
})
// 其他代码不变...
</script>
启动项目,进入待办列表页,会看到从接口获取的 10 条待办数据,验证 GET 请求功能。
(2)新增 / 删除 / 修改待办
- 新增:输入待办内容,点击 "添加",会调用 POST 接口,新增成功后显示成功提示,列表同步更新;
- 删除:点击待办项的删除按钮,调用 DELETE 接口,删除成功后显示提示,列表同步移除该项目;
- 修改状态:后续结合 Element Plus 的复选框实现,调用 PUT 接口修改完成状态。
三、核心实操二:Element Plus 入门 ------ 快速搭建美观界面
1. 步骤 1:全局注册 Element Plus(全局可用组件)
修改src/main.js,引入 Element Plus 和样式,全局注册后,所有组件都能直接使用:
javascript
运行
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router'
import App from './App.vue'
import './style.css'
// 引入Element Plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 引入Element Plus图标(可选,用于删除、编辑等图标)
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus) // 注册Element Plus
// 注册所有图标(全局可用)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.mount('#app')
2. 步骤 2:用 Element Plus 组件优化页面(以 TodoList.vue 为例)
替换原生 HTML 元素为 Element Plus 组件,优化样式和交互,修改TodoList.vue的<template>和<style>部分:
vue
<template>
<div class="todo-list-page">
<!-- 页面标题:用ElPageHeader组件 -->
<el-page-header content="待办事项列表" />
<!-- 统计信息:用ElCard组件 -->
<el-card class="stat-card" shadow="hover">
<div class="stat-item">
<span class="label">总待办:</span>
<span class="value">{{ todoStore.todoCount }}</span>
</div>
<div class="stat-item">
<span class="label">已完成:</span>
<span class="value completed">{{ todoStore.completedCount }}</span>
</div>
<div class="stat-item">
<span class="label">未完成:</span>
<span class="value uncompleted">{{ todoStore.todoCount - todoStore.completedCount }}</span>
</div>
</el-card>
<!-- 新增待办:用ElInput、ElButton组件 -->
<el-row class="add-todo" :gutter="16">
<el-col :span="18">
<el-input
v-model="newTodo"
placeholder="请输入新的待办事项"
clearable // 带清空按钮
/>
</el-col>
<el-col :span="6">
<el-button
type="primary"
@click="addTodo"
icon="Plus" // 图标
class="w-100"
>
新增待办
</el-button>
</el-col>
</el-row>
<!-- 待办列表:用ElList、ElListItem、ElCheckbox、ElButton组件 -->
<el-list class="todo-list" border :loading="todoStore.loading">
<el-list-item
v-for="(todo, index) in todoStore.todoList"
:key="todo.id"
class="todo-item"
>
<!-- 复选框:绑定完成状态 -->
<el-checkbox
v-model="todo.completed"
@change="(val) => todoStore.updateTodoStatus(todo.id, val)"
>
<!-- 已完成的待办加删除线 -->
<span :class="{ 'completed-text': todo.completed }">{{ todo.title }}</span>
</el-checkbox>
<!-- 操作按钮:删除 -->
<el-button
type="text"
icon="Delete"
class="delete-btn"
@click="todoStore.deleteTodo(todo.id)"
/>
</el-list-item>
<!-- 空状态提示:列表为空时显示 -->
<template #empty>
<el-empty description="暂无待办事项,快去新增吧!" />
</template>
</el-list>
<!-- 返回首页按钮 -->
<el-button
type="text"
icon="ArrowLeft"
@click="$router.push('/')"
class="back-btn"
>
返回首页
</el-button>
</div>
</template>
<style scoped>
.todo-list-page {
padding: 20px;
}
.stat-card {
margin: 16px 0;
}
.stat-item {
display: inline-block;
margin-right: 24px;
font-size: 14px;
}
.label {
color: #666;
margin-right: 8px;
}
.value {
font-weight: 500;
}
.completed {
color: #42b983;
}
.uncompleted {
color: #f56c6c;
}
.add-todo {
margin: 16px 0;
}
.todo-list {
margin: 16px 0;
}
.todo-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.completed-text {
text-decoration: line-through;
color: #999;
}
.delete-btn {
color: #f56c6c;
}
.back-btn {
margin-top: 16px;
}
</style>
3. Element Plus 核心功能实操验证
(1)组件美观度提升
启动项目后,待办列表页会呈现以下优化效果:
- 标题带返回箭头,统计信息用卡片展示,视觉层次清晰;
- 输入框带清空按钮,按钮带图标,交互更友好;
- 待办列表带边框和加载动画,为空时显示空状态提示,用户体验更佳。
(2)响应式适配
缩小浏览器窗口到手机尺寸,会发现页面元素自动适配(比如新增待办的输入框和按钮会换行显示),无需额外写响应式 CSS,验证 Element Plus 的响应式特性。
四、综合实战:升级为 "前后端交互 + 美观界面" 的待办应用
1. 实战目标
整合 Axios 和 Element Plus,实现一个企业级标准的待办应用:
- 数据层:从免费测试接口获取待办数据,支持新增、删除、修改状态,数据同步到接口;
- 界面层:用 Element Plus 组件搭建美观、响应式的界面,包含统计卡片、加载动画、空状态提示;
- 交互层:添加成功 / 失败提示、加载状态反馈,优化用户操作体验。
2. 完整流程测试
- 启动项目,访问首页,点击 "进入待办列表";
- 页面加载时显示加载动画,加载完成后展示 10 条待办数据和统计信息;
- 输入待办内容(比如 "学习 Axios"),点击 "新增待办",显示成功提示,列表新增该项目;
- 勾选待办前的复选框,显示 "待办已完成" 提示,文字变为删除线;
- 点击待办项右侧的删除图标,显示成功提示,列表移除该项目;
- 删除所有待办,页面显示空状态提示。
3. 新手优化建议
- 新增筛选功能:用 Element Plus 的
ElSelect组件实现 "全部 / 已完成 / 未完成" 筛选; - 新增编辑功能:点击待办项弹出
ElDialog(弹窗),用ElInput输入修改后的内容,调用 PUT 接口更新; - 优化错误处理:在 Axios 拦截器中添加网络异常、接口超时的差异化提示;
- 新增分页功能:用 Element Plus 的
ElPagination组件,实现待办数据分页加载(测试接口支持_page和_limit参数)。
五、本节课总结与下节课预告
1. 本节课核心收获
- HTTP 请求(Axios):掌握 Axios 的全局配置、接口封装、请求 / 响应拦截,实现前后端数据交互;
- UI 库(Element Plus):掌握 Element Plus 的全局注册、常用组件(卡片、按钮、输入框等)的使用,快速搭建美观界面;
- 项目升级:从 "本地数据 + 原生界面" 升级为 "前后端交互 + 企业级界面",理解企业开发的技术栈组合。
2. 课后作业(必做)
- 独立复现本节课的 Axios 配置、接口封装和 Element Plus 组件使用,完成前后端交互的待办应用;
- 实现优化需求:新增 "待办筛选"(全部 / 已完成 / 未完成)和 "待办编辑" 功能;
- 优化数据持久化:结合
localStorage,在接口请求失败时,优先使用本地存储的缓存数据; - 整理踩坑笔记:比如 "Axios 请求异步需要用 async/await""Element Plus 组件属性大小写敏感" 等。
3. 下节课预告
下节课我们将学习 "Vue 3 工程化与项目部署实战",解决 "项目打包优化" 和 "上线部署" 的问题 ------ 比如用 Vite 优化打包体积、配置环境变量(开发 / 测试 / 生产)、将项目部署到 Netlify 或 GitHub Pages,让你的应用能被全球用户访问,完成从 "本地开发" 到 "线上发布" 的完整流程!