第 5 课:Vue 3 HTTP 请求与 UI 库实战 —— 从本地数据到前后端交互应用

在前 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文件,若出现axioselement-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,实现一个企业级标准的待办应用:

  1. 数据层:从免费测试接口获取待办数据,支持新增、删除、修改状态,数据同步到接口;
  2. 界面层:用 Element Plus 组件搭建美观、响应式的界面,包含统计卡片、加载动画、空状态提示;
  3. 交互层:添加成功 / 失败提示、加载状态反馈,优化用户操作体验。

2. 完整流程测试

  1. 启动项目,访问首页,点击 "进入待办列表";
  2. 页面加载时显示加载动画,加载完成后展示 10 条待办数据和统计信息;
  3. 输入待办内容(比如 "学习 Axios"),点击 "新增待办",显示成功提示,列表新增该项目;
  4. 勾选待办前的复选框,显示 "待办已完成" 提示,文字变为删除线;
  5. 点击待办项右侧的删除图标,显示成功提示,列表移除该项目;
  6. 删除所有待办,页面显示空状态提示。

3. 新手优化建议

  1. 新增筛选功能:用 Element Plus 的ElSelect组件实现 "全部 / 已完成 / 未完成" 筛选;
  2. 新增编辑功能:点击待办项弹出ElDialog(弹窗),用ElInput输入修改后的内容,调用 PUT 接口更新;
  3. 优化错误处理:在 Axios 拦截器中添加网络异常、接口超时的差异化提示;
  4. 新增分页功能:用 Element Plus 的ElPagination组件,实现待办数据分页加载(测试接口支持_page_limit参数)。

五、本节课总结与下节课预告

1. 本节课核心收获

  • HTTP 请求(Axios):掌握 Axios 的全局配置、接口封装、请求 / 响应拦截,实现前后端数据交互;
  • UI 库(Element Plus):掌握 Element Plus 的全局注册、常用组件(卡片、按钮、输入框等)的使用,快速搭建美观界面;
  • 项目升级:从 "本地数据 + 原生界面" 升级为 "前后端交互 + 企业级界面",理解企业开发的技术栈组合。

2. 课后作业(必做)

  1. 独立复现本节课的 Axios 配置、接口封装和 Element Plus 组件使用,完成前后端交互的待办应用;
  2. 实现优化需求:新增 "待办筛选"(全部 / 已完成 / 未完成)和 "待办编辑" 功能;
  3. 优化数据持久化:结合localStorage,在接口请求失败时,优先使用本地存储的缓存数据;
  4. 整理踩坑笔记:比如 "Axios 请求异步需要用 async/await""Element Plus 组件属性大小写敏感" 等。

3. 下节课预告

下节课我们将学习 "Vue 3 工程化与项目部署实战",解决 "项目打包优化" 和 "上线部署" 的问题 ------ 比如用 Vite 优化打包体积、配置环境变量(开发 / 测试 / 生产)、将项目部署到 Netlify 或 GitHub Pages,让你的应用能被全球用户访问,完成从 "本地开发" 到 "线上发布" 的完整流程!

相关推荐
CES_Asia2 小时前
机器人“奥运会”登陆!CES Asia 2026角逐消费级机器人王座
大数据·人工智能·科技·机器人
踢球的打工仔2 小时前
ajax的基本使用(上传文件)
前端·javascript·ajax
樊小肆2 小时前
ollmam+langchain.js实现本地大模型简单记忆对话-内存版
前端·langchain·aigc
wayuncn2 小时前
AI领域核心概念解析:模型、模型参数、模型大小、计算精度
人工智能·ai·ai智能体·ai定制开发
徐小夕2 小时前
pxcharts 多维表格开源!一款专为开发者和数据分析师打造的轻量化智能表格
前端·架构·github
小陈phd2 小时前
大语言模型实战(三)——词编码技术演进:从 “机器识字符” 到 “AI 懂语义”
人工智能·语言模型·自然语言处理
电商API&Tina2 小时前
跨境电商速卖通(AliExpress)数据采集与 API 接口接入全方案
大数据·开发语言·前端·数据库·人工智能·python
得贤招聘官2 小时前
招聘终极战场:AI重构首轮筛选的精准与效能革命
人工智能·重构
通义灵码2 小时前
使用记忆提升开发效率
人工智能·qoder·记忆能力