六、【前端启航篇】Vue3 项目初始化与基础布局:搭建美观易用的管理界面骨架
【前端启航篇】Vue3 项目初始化与基础布局:搭建美观易用的管理界面骨架
- 前言
- 技术选型回顾与准备
- 准备工作
- 第一步:进入前端项目并安装 Element Plus
- 第二步:在 Vue3 项目中引入并配置 Element Plus
- 第三步:设计基础页面布局组件
- 第四步:配置路由以使用新布局
- 第五步:最终效果预览
- 总结
前言
还记得我们在【环境搭建篇】中创建的 Vue3 项目吗?当时我们只是简单地验证了它能跑起来。现在,我们要在这个基础上,为我们的测试平台精心设计一个用户界面。
一个好的管理界面通常包含以下几个部分:
- 顶部导航栏 (Header/Navbar): 通常放置 Logo、项目名称、用户信息、退出登录等。
- 侧边导航栏 (Sidebar/Aside): 用于展示主要的导航菜单,如项目管理、用例管理、测试报告等。
- 主内容区 (Main Content Area): 显示当前导航对应的具体页面内容。
我们将采用这种经典的三段式布局。
技术选型回顾与准备
- Vue3: 我们选择的渐进式 JavaScript 框架。
- Vite: 现代化的前端构建工具,提供极速的冷启动和热更新。
- TypeScript: 为 JavaScript 添加静态类型,增强代码健壮性和可维护性。
- Vue Router: 官方路由管理器,用于实现单页应用 (SPA) 的页面导航。
- Pinia: Vue3 推荐的状态管理库,轻量且易用。
- UI 组件库: 为了快速搭建美观且功能丰富的界面,我们不会从零开始手写每一个按钮、表单、表格。而是会选择一个成熟的 Vue3 UI 组件库。常见的选择有:
- Element Plus: Element UI 的 Vue3 版本,国内用户多,文档友好。
- Ant Design Vue: Ant Design 的 Vue 实现,功能强大,设计精美。
- Naive UI: 一个比较新的 Vue3 组件库,TypeScript友好,主题可定制性强。
在本专栏中,我们将选择 Element Plus 作为我们的 UI 组件库,因为它上手快,组件丰富,社区活跃,非常适合快速开发企业级中后台产品。
准备工作
- Node.js 环境: 确保你已经按照【环境搭建篇】安装好了 Node.js (LTS 版本) 和 npm/yarn/pnpm。
- 前端项目已创建: 确保你已经拥有一个通过
npm create vue@latest
创建的 Vue3 + TypeScript + Vite 项目(在【环境搭建篇】中,我们将其命名为frontend
,位于test-platform/frontend
目录下)。 - 代码编辑器: 如 VS Code,并安装推荐的 Vue 相关插件 (如 Volar)。
- 后端 API 运行中 (可选但推荐): 虽然本篇主要聚焦前端布局,但后续很快会进行前后端联调,所以最好保持你的 Django 后端开发服务器 (
python manage.py runserver
) 在后台运行。
第一步:进入前端项目并安装 Element Plus
-
打开终端,进入前端项目目录:
cd path/to/your/test-platform/frontend
-
安装 Element Plus:
我们将使用 npm 来安装 Element Plus。npm install element-plus --save
--save
会将element-plus
添加到项目的dependencies
中(现在 npm 默认行为就是这样,但明确写上更好)。Element Plus 还提供了一些图标,我们也一并安装:
npm install @element-plus/icons-vue --save
第二步:在 Vue3 项目中引入并配置 Element Plus
有多种引入 Element Plus 的方式(全局引入、按需引入)。为了学习和开发的便捷性,我们先采用全局引入的方式。当项目体积变得非常大,需要优化时,再考虑按需引入。
-
修改
src/main.ts
文件:
这是我们 Vue 应用的入口文件。我们需要在这里引入 Element Plus 的样式和组件。打开
test-platform/frontend/src/main.ts
文件,修改如下:
// test-platform/frontend/src/main.tsimport { createApp } from 'vue' import { createPinia } from 'pinia' // 1. 导入 Element Plus 组件和样式 import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' // 导入 Element Plus 的中文语言包 (可选) import zhCn from 'element-plus/dist/locale/zh-cn.mjs'import App from './App.vue' import router from './router'import './assets/main.css' // 你可以保留或删除这个默认样式,我们将使用 Element Plus 的样式为主const app = createApp(App)app.use(createPinia()) app.use(router)// 2. 全局注册 Element Plus // 并设置中文语言包 app.use(ElementPlus, { locale: zhCn })// 如果需要全局注册 Element Plus 图标 (不推荐,但作为快速上手方式) // import * as ElementPlusIconsVue from '@element-plus/icons-vue' // for (const [key, component] of Object.entries(ElementPlusIconsVue)) { // app.component(key, component) // }app.mount('#app')
代码解释:
import ElementPlus from 'element-plus'
:导入 Element Plus 插件本身。import 'element-plus/dist/index.css'
:导入 Element Plus 的全局 CSS 样式。这是必须的,否则组件会没有样式。import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
:导入中文语言包。Element Plus 默认是英文,如果需要中文界面,需要引入并配置。app.use(ElementPlus, { locale: zhCn })
:通过app.use()
来安装 Element Plus 插件,并传入配置对象{ locale: zhCn }
来设置默认语言为中文。- 关于图标:
- 我注释掉了全局引入所有图标的代码,因为它会增大打包体积。
import '@element-plus/icons-vue/dist/index.css'
也是一种全局引入图标样式的方式,但不灵活。- 最佳实践是按需引入图标组件,例如在某个
.vue
文件中import { User, Lock } from '@element-plus/icons-vue'
,然后在模板中使用<el-icon><User /></el-icon>
。我们后续会采用这种方式。现在为了让 Element Plus 的一些内置带图标的组件(如 Input 带清空图标)能正常显示,element-plus/dist/index.css
已经包含了基础的图标支持。
-
清理默认样式和组件 (可选但推荐):
Vite 创建的项目会带有一些默认的欢迎页面内容和样式。为了不干扰我们后续的布局,可以清理一下。-
src/App.vue
:
将<template>
中的内容替换为最简单的路由出口:
<!-- test-platform/frontend/src/App.vue --> <script setup lang="ts"> import { RouterView } from 'vue-router' </script><template><RouterView /> </template><style scoped> /* 可以删除这里原有的样式 */ </style>
-
src/views/HomeView.vue
和src/views/AboutView.vue
:
暂时保留src/views/AboutView.vue
,将HomeView.vue
文件内容修改成 :
<!-- test-platform/frontend/src/views/HomeView.vue --> <template><div class="home"><h1>这是首页</h1><el-button type="primary">Element Plus 按钮</el-button></div> </template><script setup lang="ts"> // 测试 Element Plus 是否生效 </script>
-
src/components/
目录:
可以删除TheWelcome.vue
,WelcomeItem.vue
,HelloWorld.vue
文件, 以及icons
文件夹,因为我们不再使用它们。
-
src/assets/main.css
:
这个文件,只保留一些非常基础的全局重置样式。Element Plus 已经有自己的 reset 和 base 样式。
/* test-platform/frontend/src/assets/main.css*/ body {margin: 0;font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale; }
-
-
启动前端开发服务器验证 Element Plus:
npm run dev
打开浏览器访问 Vite 提供的地址 (通常是
http://localhost:5173/
)。如果你在HomeView.vue
中添加了<el-button>
,你应该能看到一个带有 Element Plus 样式的按钮。
如果按钮显示正常且是 Element Plus 的风格,说明集成成功!
第三步:设计基础页面布局组件
我们将创建一个名为 Layout.vue
的组件,作为我们后台管理界面的整体框架。
-
创建
src/layout/index.vue
文件:
在src
目录下创建一个layout
文件夹,并在其中创建index.vue
文件。
-
编写
Layout.vue
的基本结构:
我们将使用 Element Plus 提供的ElContainer
,ElHeader
,ElAside
,ElMain
容器组件来搭建经典布局。<!-- test-platform/frontend/src/layout/index.vue --> <template><el-container class="app-layout"><el-header class="app-header"><div class="logo-title"><img src="@/assets/logo.svg" alt="Logo" class="logo" /><span class="title">测试平台</span></div><div class="user-info"><!-- 用户信息和退出登录等 --><el-dropdown><span class="el-dropdown-link">欢迎, Admin <el-icon class="el-icon--right"><arrow-down /></el-icon></span><template #dropdown><el-dropdown-menu><el-dropdown-item>个人中心</el-dropdown-item><el-dropdown-item>修改密码</el-dropdown-item><el-dropdown-item divided>退出登录</el-dropdown-item></el-dropdown-menu></template></el-dropdown></div></el-header><el-container class="app-body"><el-aside width="200px" class="app-aside"><el-menudefault-active="1"class="el-menu-vertical-demo"router><el-menu-item index="/"><el-icon><HomeFilled /></el-icon><span>首页</span></el-menu-item><el-sub-menu index="/project"><template #title><el-icon><Folder /></el-icon><span>项目管理</span></template><el-menu-item index="/project/list">项目列表</el-menu-item><el-menu-item index="/project/create">新建项目</el-menu-item></el-sub-menu><el-menu-item index="/testcases"><el-icon><List /></el-icon><span>用例管理</span></el-menu-item><el-menu-item index="/reports"><el-icon><DataAnalysis /></el-icon><span>测试报告</span></el-menu-item></el-menu></el-aside><el-main class="app-main"><RouterView /> <!-- 子路由的出口 --></el-main></el-container></el-container> </template><script setup lang="ts"> import { RouterView } from 'vue-router' // 导入需要的 Element Plus 图标 import { ArrowDown, HomeFilled, Folder, List, DataAnalysis } from '@element-plus/icons-vue'// 假设你有一个 logo 文件放在 src/assets/logo.svg // 如果没有,可以暂时注释掉 img 标签或用文字代替 </script><style scoped lang="scss"> // 使用 SCSS 方便样式编写 .app-layout {height: 100vh; // 整个布局占满视口高度background-color: #f0f2f5; }.app-header {background-color: #fff;color: #333;display: flex;justify-content: space-between;align-items: center;padding: 0 20px;border-bottom: 1px solid #e6e6e6;.logo-title {display: flex;align-items: center;.logo {height: 40px; // 根据你的logo调整margin-right: 10px;}.title {font-size: 20px;font-weight: bold;}}.user-info {.el-dropdown-link {cursor: pointer;display: flex;align-items: center;}} }.app-body {height: calc(100vh - 60px); // 减去 Header 的高度 (假设 Header 高度为 60px) }.app-aside {background-color: #fff;border-right: 1px solid #e6e6e6;.el-menu {border-right: none; // 移除 el-menu 默认的右边框,因为 el-aside 已经有边框了height: 100%; // 菜单占满侧边栏高度} }.app-main {padding: 20px;background-color: #fff; // 主内容区背景margin: 15px; // 添加一些外边距,使其看起来不那么拥挤border-radius: 4px; // 轻微圆角box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); // 轻微阴影 } </style>
注意:
-
Logo: 上面的代码中引用了
src/assets/logo.svg
。你需要准备一个 logo 文件,或者暂时移除<img>
标签。你可以从 iconfont.cn 或其他地方找一个合适的 SVG 图标作为 logo。 -
SCSS: 样式部分使用了
lang="scss"
。如果你的项目还没有安装sass
预处理器,需要安装一下:npm install sass --save-dev
-
<el-menu router>
:router
属性使得el-menu-item
的index
属性可以作为路由路径,点击时会自动导航。 -
图标导入: 我们按需导入了
ArrowDown
,HomeFilled
等图标组件。
-
第四步:配置路由以使用新布局
现在我们有了 Layout.vue
组件,需要修改路由配置,让大部分页面都在这个布局内显示。通常登录页、404 页等不需要这个布局。
-
修改
src/router/index.ts
文件:
// test-platform/frontend/src/router/index.ts import { createRouter, createWebHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' import Layout from '@/layout/index.vue' // 导入我们的布局组件const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',component: Layout, // 使用 Layout 作为根路径的组件redirect: '/dashboard', // 重定向到仪表盘或首页children: [ // Layout 的子路由将会在 Layout 组件的 <RouterView /> 中显示{path: 'dashboard', // 注意这里是相对路径,完整路径是 /dashboardname: 'dashboard',component: HomeView, // 假设 HomeView 是我们的仪表盘/首页meta: { title: '仪表盘' } // 可以添加 meta 信息,如页面标题},{path: '/project/list', // 示例:项目列表页 (绝对路径,但通常建议子路由用相对路径)name: 'projectList',// 稍后我们会为这些路径创建实际的组件component: () => import('../views/project/ProjectListView.vue'),meta: { title: '项目列表' }},{path: '/project/create',name: 'projectCreate',component: () => import('../views/project/ProjectCreateView.vue'),meta: { title: '新建项目' }},// ... 其他需要在布局内显示的页面{path: '/testcases',name: 'testcases',component: () => import('../views/project/TestCaseListView.vue'),meta: { title: '用例管理' }},{path: '/reports',name: 'reports',component: () => import('../views/project/ReportListView.vue'),meta: { title: '测试报告' }}]},{path: '/login', // 登录页通常不需要布局name: 'login',component: () => import('../views/LoginView.vue'), // 稍后创建meta: { title: '登录' }},// 404 页面 (可选)// {// path: '/:pathMatch(.*)*',// name: 'NotFound',// component: () => import('../views/NotFoundView.vue')// }] })// 简单的路由守卫示例 (可选,后续会详细讲权限) // router.beforeEach((to, from, next) => { // document.title = `${to.meta.title} - 测试平台` || '测试平台'; // // 假设检查 token 是否存在 // // const token = localStorage.getItem('token'); // // if (to.name !== 'login' && !token) next({ name: 'login' }); // // else next(); // next(); // });export default router
代码解释:
- 我们创建了一个父路由,其
path
为/
,component
为我们刚创建的Layout
组件。 redirect: '/dashboard'
表示访问根路径/
时,会自动跳转到/dashboard
。children
数组中定义了所有需要在Layout
内部显示的子页面。这些子页面的组件将会在Layout.vue
中的<RouterView />
处渲染。component: () => import('../views/project/ProjectListView.vue')
这种写法是路由懒加载,意味着对应的组件只会在访问该路由时才会被加载,有助于优化初始加载时间。- 我们为一些示例页面(如
ProjectListView.vue
,LoginView.vue
)预留了位置,你需要创建这些文件,即使它们暂时是空的。
- 我们创建了一个父路由,其
-
创建占位视图组件:
为了让路由能正常工作,我们需要创建上面路由配置中引用的视图文件。
在src/views/
目录下创建以下文件夹和文件(内容可以非常简单,只是为了占位):-
src/views/LoginView.vue
:<template><div><h1>登录页面</h1><el-input placeholder="用户名"></el-input><el-input placeholder="密码" type="password"></el-input><el-button type="primary">登录</el-button></div> </template>
-
src/views/project/ProjectListView.vue
:<template><div><h2>项目列表</h2><!-- 后续会填充真实内容 --></div> </template>
-
src/views/project/ProjectCreateView.vue
:<template><div><h2>新建项目</h2></div> </template>
-
src/views/testcase/TestCaseListView.vue
:<template><div><h2>用例管理</h2></div> </template>
-
src/views/report/ReportListView.vue
:<template><div><h2>测试报告</h2></div> </template>
-
修改
src/views/HomeView.vue
作为我们的仪表盘页面 (Dashboard):<!-- src/views/HomeView.vue --> <template><div class="dashboard"><h1>欢迎来到测试平台仪表盘</h1><p>这里将展示一些汇总信息和快速入口。</p><el-card class="box-card" style="margin-top: 20px;"><template #header><div class="card-header"><span>快速开始</span></div></template><el-button type="primary" @click="$router.push('/project/list')">查看项目</el-button><el-button type="success" @click="$router.push('/testcases')">管理用例</el-button></el-card></div> </template><script setup lang="ts"> // import { useRouter } from 'vue-router' (如果不用 $router) // const router = useRouter() </script>
-
第五步:最终效果预览
现在,再次运行你的前端开发服务器:
npm run dev
打开浏览器访问 http://localhost:5173/
你应该能看到:
- 页面自动跳转到
/dashboard
。 - 展示了我们设计的
Layout.vue
布局:顶部有 Logo 和标题、用户信息下拉框;左侧有导航菜单;中间是HomeView.vue
(仪表盘) 的内容。 - 点击左侧导航菜单(如“项目列表”、“用例管理”),中间主内容区会切换到对应的占位页面内容,并且浏览器 URL 也会相应改变。
- 尝试直接访问
http://localhost:5173/login
,你会看到登录页面,它没有应用我们的Layout
布局。
总结
在这篇文章中,我们完成了前端项目的初始化和基础布局的搭建:
- ✅ 安装并全局引入了 Element Plus UI 组件库及其样式和中文语言包。
- ✅ 清理了 Vue 项目的默认组件和样式。
- ✅ 使用 Element Plus 的容器组件设计并实现了一个经典的三段式后台管理布局 (
Layout.vue
),包含顶部导航、侧边菜单和主内容区。 - ✅ 按需导入了 Element Plus 图标。
- ✅ 配置了 Vue Router,使大部分页面能够共享
Layout.vue
布局,并实现了路由懒加载。 - ✅ 创建了几个占位视图组件,以确保路由正常工作。
- ✅ 预览了基础布局的运行效果。
我们现在有了一个坚实的前端基础。在下一篇文章中,我们将更深入地探讨 Vue Router 的使用,包括动态路由、导航守卫(用于权限控制)等,让我们的页面导航更加强大和灵活。