当前位置: 首页 > news >正文

Vue 学习与实践大纲(后端视角)

Vue 学习与实践大纲(后端视角)

作为一个后端大数据开发人员,对于前端不必深究;重点掌握 Vue 框架的基本用法和常用 UI 组件(Element Plus),并结合大模型的代码生成能力,快速产出可维护的管理后台页面。关键是做好“组件抽象”,让生成的代码结构清晰、可复用、易扩展。

学习目标

  • 能独立完成典型 CRUD 列表页(搜索、表格、分页、弹窗表单)。
  • 会用组合式 API(setuprefcomputedwatch)。
  • 掌握 Element Plus 常用组件并能抽象为通用组件。
  • 会封装 Axios 请求与路由守卫,完成登录鉴权与错误处理。
  • 能用 LLM 生成前端骨架,并通过约束让组件结构可复用。

快速入门要点

  • 组件与响应式:用 ref/reactive 管理局部状态,computed 计算派生值。
  • 路由与布局:vue-router 定义页面与主布局,登录后进入主框架。
  • UI 组件:Element Plus 的表格、表单、弹窗、消息、日期、上传。
  • 状态管理:Pinia 最小使用(如 userStore 存 token、用户信息)。
  • 网络请求:Axios 封装,统一注入 Token,统一错误提示与重试策略。
  • 权限控制:路由守卫 + 指令/组件控制按钮级权限。
  • 组件抽象:props/emits/slots 约定,维持单一职责与低耦合。

目录结构建议

src/api/           接口请求封装与模块components/    可复用基础组件(表格、搜索区、分页、上传等)router/        路由与守卫stores/        Pinia storesutils/         工具方法(时间、下载、权限判断等)views/         业务页面(列表、编辑、详情)

Element Plus 必会组件

  • 数据展示:ElTableElPaginationElCard
  • 表单:ElFormElInputElSelectElDatePickerElUpload
  • 反馈:ElMessageElMessageBoxElDialogElNotification
  • 布局:ElContainerElHeaderElAsideElMainElRowElCol

网络与权限

  • Axios:创建实例,request 拦截器写入 token;response 统一处理。
  • 路由守卫:在 beforeEach 判断登录状态与权限,未登录跳转登录页。

组件抽象与复用原则

  • 单一职责:展示组件不直接调接口,数据与分页交由外层控制。
  • 事件导向:用 emits 暴露事件,让外层掌控行为与数据。
  • 插槽扩展:复杂单元格、操作列通过 slots 扩展实现。
  • 低耦合:组件避免直接依赖 store 或路由,必要数据用 props 注入。
  • 可组合:通用逻辑封为 composable(如 usePaginationuseSearchForm)。

最小项目初始化与依赖

  • 环境:Node 18+,包管理器 npmpnpm
  • 初始化命令(Windows PowerShell):
npm create vite@latest my-admin -- --template vue
cd my-admin
npm i element-plus axios pinia vue-router

入口示例(src/main.ts):

import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import router from './router'
import { createPinia } from 'pinia'const app = createApp(App)
app.use(router)
app.use(createPinia())
app.use(ElementPlus)
app.mount('#app')

基础路由(src/router/index.ts):

import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(),routes: [{ path: '/', component: () => import('../views/Home.vue') },{ path: '/login', component: () => import('../views/Login.vue') }]
})export default router

用户状态(src/stores/user.ts):

import { defineStore } from 'pinia'export const useUserStore = defineStore('user', {state: () => ({ token: '' }),actions: { setToken(t: string) { this.token = t } }
})

请求封装(src/api/http.ts):

import axios from 'axios'const http = axios.create({ baseURL: '/api', timeout: 10000 })http.interceptors.request.use((config) => {// 注入 token(示例):// const token = localStorage.getItem('token')// if (token) config.headers.Authorization = `Bearer ${token}`return config
})http.interceptors.response.use((res) => res.data,(err) => Promise.reject(err)
)export default http

通用表格组件约定与示例

约定:

  • props:columnsdataloadingpagination({ page, pageSize, total })
  • emits:update:paginationrow-clickselection-changerefresh
  • slots:toolbarcell-[columnKey]

示例组件(src/components/TablePro.vue):

<template><div><slot name="toolbar" /><el-table:data="data":loading="loading"@row-click="(row) => emit('row-click', row)"@selection-change="(rows) => emit('selection-change', rows)"><el-table-column type="selection" width="48" /><el-table-columnv-for="col in columns":key="col.key":prop="col.key":label="col.label":width="col.width":align="col.align || 'left'"><template #default="scope"><slot :name="`cell-${col.key}`" :row="scope.row">{{ scope.row[col.key] }}</slot></template></el-table-column></el-table><el-paginationv-if="pagination"class="mt-12"backgroundlayout="prev, pager, next, sizes, total":current-page="pagination.page":page-size="pagination.pageSize":total="pagination.total"@update:current-page="(p) => emit('update:pagination', { page: p, pageSize: pagination.pageSize })"@update:page-size="(s) => emit('update:pagination', { page: 1, pageSize: s })"/></div></template><script setup lang="ts">
import type { PropType } from 'vue'interface Column { key: string; label: string; width?: number; align?: 'left'|'center'|'right' }const props = defineProps({columns: { type: Array as PropType<Column[]>, required: true },data: { type: Array as PropType<any[]>, default: () => [] },loading: { type: Boolean, default: false },pagination: {type: Object as PropType<{ page: number; pageSize: number; total: number }>,default: undefined}
})const emit = defineEmits<{(e: 'update:pagination', v: { page: number; pageSize: number }): void(e: 'row-click', v: any): void(e: 'selection-change', v: any[]): void(e: 'refresh'): void
}>()
</script>

列表页示例(src/views/UserList.vue):

<template><el-card><TablePro:columns="columns":data="rows":loading="loading":pagination="pagination"@update:pagination="onPage"><template #toolbar><el-form :inline="true" :model="query"><el-form-item label="关键字"><el-input v-model="query.keyword" placeholder="用户名称" /></el-form-item><el-form-item><el-button type="primary" @click="fetchList">查询</el-button><el-button @click="reset">重置</el-button></el-form-item></el-form></template><template #cell-actions="{ row }"><el-button size="small" @click="edit(row)">编辑</el-button></template></TablePro></el-card></template><script setup lang="ts">
import { ref, reactive } from 'vue'
import TablePro from '../components/TablePro.vue'const columns = [{ key: 'id', label: 'ID', width: 80 },{ key: 'name', label: '姓名' },{ key: 'phone', label: '手机' },{ key: 'actions', label: '操作', width: 160, align: 'center' }
]const query = reactive({ keyword: '' })
const rows = ref<any[]>([])
const loading = ref(false)
const pagination = ref({ page: 1, pageSize: 10, total: 0 })function onPage(v: { page: number; pageSize: number }) {pagination.value.page = v.pagepagination.value.pageSize = v.pageSizefetchList()
}function reset() {query.keyword = ''pagination.value.page = 1fetchList()
}async function fetchList() {loading.value = truetry {// 替换为真实接口const total = 42const start = (pagination.value.page - 1) * pagination.value.pageSizeconst end = start + pagination.value.pageSizeconst data = Array.from({ length: total }).map((_, i) => ({ id: i + 1, name: `用户${i + 1}`, phone: '13800000000' }))rows.value = data.slice(start, end)pagination.value.total = total} finally {loading.value = false}
}function edit(row: any) {console.log('edit', row)
}fetchList()
</script>

LLM 提示词模板(可直接用)

  • 目标:生成「Vue 3 + Element Plus」的可复用表格组件与列表页骨架。
  • 约束:
    • props:columnsdataloadingpagination
    • emits:update:paginationrow-clickselection-changerefresh
    • slots:toolbarcell-[columnKey]
    • 使用组合式 API 与 TypeScript,组件不写死接口调用。
  • 输出:组件源码、使用示例(列表页),以及最小 main.ts 接入说明。

示例提示词:

请用 Vue 3 + Element Plus 写一个通用表格组件 TablePro.vue,满足上述 props/emits/slots 约束,并给出一个在列表页中使用它的示例。列表页包含搜索区域(关键字)、分页、刷新按钮,不写死接口,仅演示事件流与数据拼装。

实践路径与常见坑

  • 路线:先定义后端接口契约 → 生成组件骨架 → 接好 Axios → 页面拼装。
  • 常见坑:
    • Vue 3 用 Element Plus(非 Element UI)。
    • 全局样式污染,尽量使用局部样式或 CSS 变量。
    • 表格数据量大时优先服务端分页,需要时做行虚拟化。
    • 表单复杂时拆分子组件,避免巨型组件。
http://www.dtcms.com/a/445833.html

相关文章:

  • 2025时序数据库选型,从架构基因到AI赋能来解析
  • 三合一网站平台做网站 如何注册公司
  • 中山今科网站建设德州百度推广公司
  • Rust 与 传统语言:现代系统编程的深度对比
  • STM32--智能小车
  • Rust 登堂 之 Cell 和 RefCell(十二)
  • 分布式追踪系统实战:OpenTelemetry集成Istio实现全链路故障定位
  • 不同光谱的工业相机有哪些?能做什么?
  • 计算机网络——数据链路层笔记整理
  • CSS高效开发三大方向
  • 网站开发中的开版什么意思宁波汽车网站建设
  • dot1q termination vid vlan-id 概念及题目
  • 在越南做一个网站怎么做百度ai开放平台
  • IEEE Transactions 风格补充材料(Word)快速排版教程
  • php 8.4.11 更新日志
  • 二分查找_优选算法(C++)二分查找算法
  • 安卓设备分区作用详解-测试机红米K40
  • 网站开发进度计划是什么长沙游戏推广
  • AI与敏捷开发管理系列4:双向赋能——AI技术如何优化敏捷实践
  • opencv cv2.MorphologyEx
  • 【多线程】读写锁(Read-Write Lock)是什么?
  • 电子商务网站建设步骤百度文库网站ip地址 a记录
  • 常规可见光相机在工业视觉检测中的应用
  • 佛山企业网站建设平台如何把官网
  • Vue3双向数据绑定v-model
  • Vue keep-alive
  • Vue中的hash模式和history模式
  • 微信网站 影楼电商网站开发代码
  • 如何更改PPT的比例大小
  • 【MediaMTX】centos 7 安装MediaMTX