Vue3+TypeScript手把手实战:一个完整的CRUD管理后台

本文带你从零搭建一个基于 Vue3 + TypeScript + Vite 的管理后台项目,包含完整的增删改查功能。无论是新手入门还是老手升级,这篇教程都能帮你快速上手 Vue3 Composition API。

一、项目初始化

首先使用 Vite 创建项目,这是目前最推荐的 Vue3 开发方式:

# 创建项目
npm create vite@latest vue3-admin -- --template vue-ts

# 进入目录
cd vue3-admin

# 安装依赖
npm install

# 安装额外需要的库
npm install vue-router@4 pinia axios element-plus @element-plus/icons-vue

项目结构大致如下:

vue3-admin/
├── src/
│   ├── api/           # API 接口
│   ├── components/    # 公共组件
│   ├── views/         # 页面视图
│   ├── stores/        # Pinia 状态管理
│   ├── types/         # TypeScript 类型
│   ├── utils/        # 工具函数
│   ├── App.vue
│   └── main.ts
├── index.html
└── package.json

二、TypeScript 类型定义

良好的类型定义是 TypeScript 的核心。先定义用户类型:

// src/types/index.ts

export interface User {
  id: number
  username: string
  email: string
  role: 'admin' | 'editor' | 'viewer'
  status: 'active' | 'inactive'
  createdAt: string
}

export interface UserForm {
  username: string
  email: string
  role: 'admin' | 'editor' | 'viewer'
  password?: string
}

export type PaginationParams = {
  page: number
  pageSize: number
}

export type ApiResponse = {
  data: T
  message: string
  code: number
}

这些类型定义贯穿整个应用,保证代码的类型安全。

三、使用 Pinia 管理状态

Pinia 是 Vue3 官方推荐的状态管理库,比 Vuex 更简洁:

// src/stores/userStore.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { User, UserForm, PaginationParams } from '@/types'
import { getUserList, createUser, updateUser, deleteUser } from '@/api/user'

export const useUserStore = defineStore('user', () => {
  // 状态
  const users = ref([])
  const loading = ref(false)
  const pagination = ref({ page: 1, pageSize: 10, total: 0 })

  // 计算属性
  const activeUsers = computed(() => 
    users.value.filter(u => u.status === 'active')
  )

  // Actions
  async function fetchUsers(params?: Partial) {
    loading.value = true
    try {
      if (params) {
        pagination.value = { ...pagination.value, ...params }
      }
      const res = await getUserList({
        page: pagination.value.page,
        pageSize: pagination.value.pageSize
      })
      users.value = res.data.list
      pagination.value.total = res.data.total
    } finally {
      loading.value = false
    }
  }

  async function addUser(form: UserForm) {
    await createUser(form)
    await fetchUsers()
  }

  async function editUser(id: number, form: UserForm) {
    await updateUser(id, form)
    await fetchUsers()
  }

  async function removeUser(id: number) {
    await deleteUser(id)
    await fetchUsers()
  }

  return {
    users,
    loading,
    pagination,
    activeUsers,
    fetchUsers,
    addUser,
    editUser,
    removeUser
  }
})

四、API 接口封装

统一管理 API 请求,便于维护和调试:

// src/api/user.ts
import axios from 'axios'
import type { User, UserForm, ApiResponse, PaginationParams } from '@/types'

const request = axios.create({
  baseURL: '/api',
  timeout: 10000
})

// 响应拦截器
request.interceptors.response.use(
  res => res.data,
  error => Promise.reject(error)
)

interface UserListResponse {
  list: User[]
  total: number
}

export async function getUserList(params: PaginationParams) {
  return request.get>('/users', { params })
}

export async function createUser(data: UserForm) {
  return request.post>('/users', data)
}

export async function updateUser(id: number, data: UserForm) {
  return request.put>(`/users/${id}`, data)
}

export async function deleteUser(id: number) {
  return request.delete>(`/users/${id}`)
}

export async function getUserDetail(id: number) {
  return request.get>(`/users/${id}`)
}

五、用户列表页面

完整的用户管理页面,包含搜索、分页、操作:






六、路由配置

配置路由守卫,保护管理页面:

// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    redirect: '/users'
  },
  {
    path: '/users',
    name: 'UserList',
    component: () => import('@/views/UserList.vue'),
    meta: { title: '用户管理' }
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login.vue'),
    meta: { title: '登录' }
  }
]

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

// 路由守卫
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')
  if (to.path !== '/login' && !token) {
    next('/login')
  } else {
    next()
  }
})

export default router

七、main.ts 入口配置

整合所有插件,启动应用:

// src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)

// Pinia
app.use(createPinia())

// Element Plus
app.use(ElementPlus)

// 注册所有图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

// 路由
app.use(router)

app.mount('#app')

八、效果展示

项目完成后,你将拥有一个完整的用户管理后台,具备以下功能:
✓ 用户列表展示与分页
✓ 按用户名/状态搜索
✓ 新增、编辑、删除用户
✓ 表单验证与错误提示
✓ 响应式布局

总结

本文展示了 Vue3 + TypeScript 开发管理后台的完整流程:

  • 使用 Vite 快速创建项目
  • TypeScript 类型定义保证类型安全
  • Pinia 管理应用状态
  • Axios 封装 API 请求
  • Element Plus 构建 UI
  • Vue Router 配置路由

这套架构可直接用于生产项目,同时支持按需扩展更多功能。掌握这些核心技能,你就能快速开发各类 Vue3 应用了。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容