Vue 学习总结(Java 后端工程师视角)

基于前后端分离项目(Vue3 + Vite + TypeScript + Pinia + Element Plus)全程类比 SpringBoot 思维,新手可直接上手

一、项目结构与核心文件作用

1. 整体结构

plaintext

java 复制代码
项目根目录
├── .vscode/           VSCode 编辑器配置
├── node_modules/      第三方依赖库(≈ Maven 本地仓库)
├── public/            静态资源(≈ SpringBoot static)
├── src/               业务源码(主要开发目录)
├── dist/              打包后部署文件(≈ target/)
├── package.json       依赖 + 启动脚本(≈ pom.xml)
└── index.html         项目入口页面

2. 关键文件说明

  • package.json :管理依赖、定义 dev/build/lint 等命令
  • node_modules/npm install 生成,不提交 Git
  • dist/npm run build 后生成,用于部署
  • public/ :存放 favicon.ico 等不参与编译的静态资源
  • src/ :页面、组件、接口、状态、路由均在此

二、项目运行与启动流程

1. 常用命令

bash

运行

arduino 复制代码
npm run dev      # 启动开发服务(≈ mvn spring-boot:run)
npm run build    # 生产打包(≈ mvn clean package)
npm install      # 安装依赖

2. 浏览器启动 Vue 流程

  1. 访问地址 → 加载 index.html
  2. 解析并加载 main.ts(项目入口)
  3. 创建 Vue 实例,挂载到 #app 节点
  4. 加载路由 → 根据 URL 渲染对应页面

3. 入口文件 main.ts(≈ 启动类)

ts

javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'

const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')

三、Pinia 状态管理(核心重点)

1. 是什么?

Pinia = 前端的 @Service + 全局单例 Bean + 内存缓存用于:全局共享数据、业务逻辑封装、接口调用、权限状态。

2. 基本结构

ts

javascript 复制代码
import { defineStore } from 'pinia'

export const useXxxStore = defineStore('唯一标识', {
  state: () => ({
    // 数据 ≈ 类成员变量
  }),
  actions: {
    // 方法 ≈ 业务逻辑(支持 async/await)
  },
  getters: {
    // 计算属性 ≈ getXxx()
  }
})

3. async /await 说明

  • async:标记为异步方法
  • await:等待异步操作完成(如接口请求)
  • 本质:异步执行,但写法像同步,避免回调嵌套

四、前后端分离接口封装

1. API 层(≈ Mapper / Dao)

ts

typescript 复制代码
// src/api/student.ts
import request from './index'

export interface Student {
  id: number
  name: string
  className: string
}

export function getStudentList(params: { page: number; pageSize: number }) {
  return request<{ list: Student[]; total: number }>({
    url: '/student/list',
    method: 'get',
    params
  })
}

2. 请求工具统一携带 Token

ts

javascript 复制代码
// src/api/index.ts
import axios from 'axios'
import { useAuthStore } from '@/stores/authStore'

const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL
})

// 请求拦截器自动加 token
request.interceptors.request.use(config => {
  const authStore = useAuthStore()
  if (authStore.token) {
    config.headers.Authorization = `Bearer ${authStore.token}`
  }
  return config
})

export default request

五、路由 Vue Router(≈ @RequestMapping)

配置示例

ts

javascript 复制代码
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  {
    path: '/student',
    component: () => import('@/views/StudentList.vue'),
    meta: { requiresAuth: true }
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

六、完整可运行示例:学生管理

1. 学生 Store(≈ Service)

ts

javascript 复制代码
// src/stores/studentStore.ts
import { defineStore } from 'pinia'
import { getStudentList, Student } from '@/api/student'

export const useStudentStore = defineStore('student', {
  state: () => ({
    list: [] as Student[],
    total: 0,
    page: 1,
    pageSize: 10,
    loading: false
  }),

  actions: {
    async fetchList() {
      this.loading = true
      try {
        const res = await getStudentList({
          page: this.page,
          pageSize: this.pageSize
        })
        this.list = res.list
        this.total = res.total
      } finally {
        this.loading = false
      }
    }
  }
})

2. 学生列表页面(≈ Controller + View)

vue

ini 复制代码
// src/views/StudentList.vue
<template>
  <el-card>
    <el-table :data="studentStore.list" v-loading="studentStore.loading">
      <el-table-column label="ID" prop="id" />
      <el-table-column label="姓名" prop="name" />
      <el-table-column label="班级" prop="className" />
    </el-table>

    <el-pagination
      v-model:current-page="studentStore.page"
      v-model:page-size="studentStore.pageSize"
      :total="studentStore.total"
      @current-change="studentStore.fetchList"
      style="margin-top:16px; text-align:right"
    />
  </el-card>
</template>

<script setup lang="ts">
import { useStudentStore } from '@/stores/studentStore'
const studentStore = useStudentStore()

studentStore.fetchList()
</script>

七、全局字典缓存(DictStore)

作用

统一管理性别、班级、状态等下拉数据,全局只请求一次

ts

javascript 复制代码
// src/stores/dictStore.ts
import { defineStore } from 'pinia'
import { getDictData } from '@/api/dict'

export const useDictStore = defineStore('dict', {
  state: () => ({
    gender: [],
    classes: []
  }),

  actions: {
    async loadDict() {
      const res = await getDictData()
      this.gender = res.gender
      this.classes = res.classes
    }
  }
})

使用方式

ts

scss 复制代码
// App.vue 中全局加载一次
const dictStore = useDictStore()
dictStore.loadDict()

// 页面中直接使用缓存
dictStore.gender
dictStore.classes

八、前后端 MVC 对应关系

表格

前端技术 Java 后端对应
Vue 页面 Controller + View
Pinia Store Service 层
API 接口 Mapper / Dao
Pinia state 成员变量 / 缓存
axios RestTemplate / WebClient
Vue Router @RequestMapping
package.json pom.xml
node_modules Maven 依赖库
dist 目录 target 编译目录

九、核心知识点总结

  1. Vue 是前端框架,相当于浏览器里的 SpringBoot
  2. Pinia 是状态管理,相当于全局 Service + 缓存
  3. async/await 用于异步请求后端接口
  4. API 层统一封装接口,便于维护和加 Token
  5. 路由控制页面跳转,类似后端接口路由
  6. 项目结构、分层思想与后端高度一致

十、学习路线(后端工程师推荐)

  1. 项目结构与文件作用
  2. 启动流程与 main.ts
  3. Pinia 基本使用
  4. 接口调用与 axios 封装
  5. 路由与登录权限
  6. 表格、表单、增删改查
  7. 全局字典、缓存、权限控制
相关推荐
计算机魔术师20 小时前
Dario Amodei 发文呼吁 AI 行业放慢前沿速度并公布三步计划
前端
EatFan20 小时前
前后端分离项目中 Token 到底应该怎么设计?Access Token + Refresh Token 实战
java·前端·后端
dsyyyyy110120 小时前
Typescript装饰器
前端·javascript·typescript
一拳不是超人21 小时前
一个没测暗色模式的 Bug,吃掉了我一半 谷歌扩展用户
前端·javascript·程序员
liangshanbo12151 天前
React useState 函数式更新面试题整理
前端·react.js·前端框架
涛涛ing1 天前
为什么你的页面在 Safari 上总出问题?Interop 2027 正在解决这个 20 年老毛病
前端
不一样的少年_1 天前
WebP 压缩到底在干嘛?小白也能看懂的原理拆解
前端·后端·图片资源
问心无愧05131 天前
ctf show web 177
前端·笔记
不一样的少年_1 天前
PNG/JPG 如何变成 WebP?真相不是改后缀!
前端·后端·图片资源
杉氧1 天前
RN 性能调优指南:重渲染(Re-renders)控制与长列表(FlatList)优化
android·前端·react native