Skip to content
第 29 章 前端 ⏱ 15 分钟阅读

第 29 章:综合实战 ​

学习目标 ​

  • 用本教程所有技术搭一个后台
  • 整合路由、Pinia、组件库、请求
  • 实现权限与表单
  • 跑通打包部署

一、需求 ​

一个简单的用户管理后台:

  • 登录 / 退出
  • 用户列表(分页 + 搜索)
  • 新增 / 编辑 / 删除 user
  • 权限控制

二、目录结构 ​

src/
├─ api/             # axios 封装 + 各模块
├─ assets/
├─ components/      # 通用组件
├─ composables/     # hooks
├─ directives/      # 自定义指令
├─ layouts/         # Layout
├─ router/          # 路由
├─ stores/          # Pinia
├─ styles/          # 全局样式
├─ utils/           # 工具
├─ views/           # 页面
├─ App.vue
└─ main.ts

三、main.ts ​

ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persistedstate'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import { router } from './router'
import './styles/index.scss'
import { permission } from './directives/permission'

const app = createApp(App)
const pinia = createPinia()
pinia.use(piniaPersist)

app.use(pinia).use(router).use(ElementPlus)
app.directive('permission', permission)
app.mount('#app')

四、Layout ​

vue
<!-- src/layouts/AdminLayout.vue -->
<script setup lang="ts">
import { useUserStore } from '@/stores/user'
import { useRouter } from 'vue-router'

const user = useUserStore()
const router = useRouter()

const logout = () => {
  user.logout()
  router.push('/login')
}
</script>

<template>
  <el-container>
    <el-aside width="220px">
      <Sidebar />
    </el-aside>
    <el-container>
      <el-header>
        <span>{{ user.name }}</span>
        <el-button @click="logout">退出</el-button>
      </el-header>
      <el-main>
        <router-view v-slot="{ Component, route }">
          <transition name="fade" mode="out-in">
            <component :is="Component" :key="route.fullPath" />
          </transition>
        </router-view>
      </el-main>
    </el-container>
  </el-container>
</template>

五、路由 + 守卫 ​

ts
router.beforeEach((to) => {
  const user = useUserStore()
  if (to.meta.requiresAuth && !user.token) return '/login'
})

六、Login 页 ​

vue
<script setup lang="ts">
import { useUserStore } from '@/stores/user'
import { useRouter } from 'vue-router'

const form = reactive({ username: '', password: '' })
const user = useUserStore()
const router = useRouter()

const submit = async () => {
  await user.login(form.username, form.password)
  router.push('/users')
}
</script>

<template>
  <el-form @submit.prevent="submit">
    <el-input v-model="form.username" />
    <el-input v-model="form.password" type="password" />
    <el-button native-type="submit">登录</el-button>
  </el-form>
</template>

七、用户列表 ​

vue
<script setup lang="ts">
import { useUserStore } from '@/stores/user'
import { userApi } from '@/api/user'

const store = useUserStore()
const list = ref<User[]>([])
const total = ref(0)
const page = ref(1)
const loading = ref(false)

const load = async () => {
  loading.value = true
  const res = await userApi.list({ page: page.value })
  list.value = res.items
  total.value = res.total
  loading.value = false
}

onMounted(load)
</script>

<template>
  <el-table :data="list" v-loading="loading">
    <el-table-column prop="id" label="ID" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column label="操作">
      <el-button v-permission="'user:delete'" type="danger">删除</el-button>
    </el-table-column>
  </el-table>
  <el-pagination v-model:current-page="page" :total="total" @current-change="load" />
</template>

八、关键点回顾 ​

技术落地
<script setup>所有组件
defineProps <{}>TS 类型
v-model表单
v-permission按钮权限
Pinia + persist状态持久化
路由守卫登录拦截
Element PlusUI 框架
axios 封装请求统一

九、本章小结 ​

步骤工具
初始化Vite + Vue 3
状态Pinia
路由vue-router
UIElement Plus
权限v-permission
部署nginx / Vercel

动手练习 ​

  1. 跑通登录:admin / 123 登录成功跳用户列表
  2. 新增用户:dialog + form,提交刷新列表
  3. 删除:带 v-permission 控制,删完刷新

下一章:第 30 章:Vue 生态资源 →

本站基于 VitePress 构建 · 由 StackHub 团队维护