目录

  1. 环境要求
  2. Vite + Vue3 搭建初始化
  3. 路由 Router 的安装和配置
  4. 配置 tsx 支持
  5. less 的安装和使用
  6. 样式统一引入
  7. ElementUI 的安装和使用
  8. vite 配置路径别名
  9. i18n 配置多语言
  10. 设计系统的 Layout UI
  11. 设计菜单栏+权限控制
  12. 设计 API 目录
  13. 配置 mock
  14. 功能页面编写

1. 环境要求

  • node:Node.js 版本 >= 12.0.0,目前使用版本:v14.16.0
  • 包管理工具:npm/yarn,目前使用的是 yarn:v1.22.10
  • 编辑器:VSCode

2. Vite + Vue3 搭建初始化

  1. 全局安装 vite
  1. yarn global add vite
  2. # 安装vite+vue3.0项目,Vite 需要 Node.js 版本 >= 12.0.0。
  3. D:/
  4. # 基于vite搭建项目,项目名:rbac-manage,前端框架使用vue,开发语言:typescript
  5. yarn create vite
  6. # √ Project name: ... rbac-manage
  7. # √ Select a framework: » vue
  8. # √ Select a variant: » vue-ts
  9. # 切换工作目录到rbac-manage,
  10. cd rbac-manage
  11. # 下载项目运行的前端依赖模块
  1. 基于 vite 搭建项目,项目名:rbac-manage,前端框架使用 vue3,开发语言:TypeScript
  1. yarn create vite
  2. # √ Project name: ... rbac-manage
  3. # √ Select a framework: » vue
  4. # √ Select a variant: » vue-ts
  1. 启动项目
  1. # 切换工作目录到rbac-manage
  2. cd rbac-manage
  3. # 下载项目运行的前端依赖模块
  4. yarn
  5. # 启动测试服务器,运行vue项目
  6. yarn dev

至此,一个由 Vite 构建的 Vue3 项目就搭建好了,支持 TypeScript 语法。

3. 路由 Router 的安装和配置

  1. 安装 vue-router 4.x
  1. yarn add vue-router@next
  1. 配置路由模块

创建src/router/index.ts,代码:

  1. import {createRouter, Router, createWebHistory, RouteRecordRaw} from 'vue-router'
  2. // 路由列表
  3. const routes:Array<RouteRecordRaw> = [
  4. // 省略,见项目src/router/index.ts具体代码
  5. ]
  6. const router:Router = createRouter({
  7. // history, 指定路由的模式
  8. history: createWebHistory(),
  9. // 路由列表
  10. routes,
  11. });
  12. export default router

根据项目的模块划分,设计项目目录和项目路由如下:

  • 创建src/views目录,然后分别添加 login 目录,member 目录,device 目录,operator 目录,point-group目录,scenario 目录,wbs 目录,每个目录添加 Index.vue 文件,作为每个模块的入口文件,如下图:
  • 更新项目路由src/router/index.ts中的 router 如下:
  1. const routes: Array<RouteRecordRaw> = [
  2. {
  3. name: "index",
  4. path: "/",
  5. redirect: "/member",
  6. },
  7. {
  8. name: "Login",
  9. path: "/login",
  10. component: () => import("../views/login/Index.vue"),
  11. },
  12. {
  13. name: "Member",
  14. path: "/member",
  15. component: () => import("../views/member/Index.vue"),
  16. },
  17. {
  18. name: "Device",
  19. path: "/device",
  20. component: () => import("../views/device/Index.vue"),
  21. },
  22. {
  23. name: "Operator",
  24. path: "/operator",
  25. component: () => import("../views/operator/Index.vue"),
  26. },
  27. {
  28. name: "PointGroup",
  29. path: "/point-group",
  30. component: () => import("../views/point-group/Index.vue"),
  31. },
  32. {
  33. name: "Scenario",
  34. path: "/scenario",
  35. component: () => import("../views/scenario/Index.vue"),
  36. },
  37. {
  38. name: "Wbs",
  39. path: "/wbs",
  40. component: () => import("../views/wbs/Index.vue"),
  41. },
  42. ];
  • 引入 router.ts 到项目中

src/main.ts文件,把 router 对象注册到项目中

  1. import { createApp } from "vue";
  2. import App from "./App.vue";
  3. import router from "./router";
  4. createApp(App).use(router).mount("#app");

src/App.vue组件中,添加显示路由对应的内容:

  1. <template>
  2. <router-view />
  3. </template>
  4. <script setup lang="ts"></script>

至此,完成项目路由切换的搭建。

4. 配置 tsx 支持

文档:https://cn.vitejs.dev/guide/features.html#jsx

  1. 安装插件
  1. yarn add -D @vitejs/plugin-vue-jsx
  1. 配置vite.config.ts
  1. import { defineConfig } from "vite";
  2. import vue from "@vitejs/plugin-vue";
  3. import vueJsx from "@vitejs/plugin-vue-jsx";
  4. // https://vitejs.dev/config/
  5. export default defineConfig({
  6. plugins: [vue(), vueJsx({})],
  7. });
  1. 配置 tsconfig.json
  1. {
  2. "compilerOptions": {
  3. "jsx": "preserve",
  4. "jsxFactory": "h",
  5. "jsxFragmentFactory": "Fragment"
  6. },
  7. "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
  8. }
  1. 测试 vue3 + tsx

在 components 目录下创建一个 TestDemo.tsx 文件,并在页面中引用,测试是否成功解析 tsx 文件:

  1. import { FunctionalComponent as FC, defineComponent, reactive, onMounted } from 'vue';
  2. // 无状态组件
  3. const FcNode: FC<{ data: number }> = ({ data }) => {
  4. return (
  5. <>
  6. <hr />
  7. <div>子组件:
  8. {data < 10 ? <span>{data}</span> : <h1>{data}</h1>}
  9. </div>
  10. </>
  11. )
  12. };
  13. // 状态组件需要使用 defineComponent
  14. export default defineComponent({
  15. name: 'TsxDemo',
  16. setup() {
  17. const data = reactive({ count: 0 });
  18. onMounted(() => {
  19. data.count = 5;
  20. });
  21. const clickHandler = () => data.count++
  22. return () => (
  23. <>
  24. <span style={{ marginRight: '10px' }}>{ data.count }</span>
  25. <button onClick={clickHandler}>+</button>
  26. <FcNode data={data.count}/>
  27. </>
  28. )
  29. }
  30. })

至此,tsx 的配置已完成。

5. less 的安装和使用

文档:https://cn.vitejs.dev/guide/features.html#css

  1. 安装
  1. yarn add less

Vite 提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持,不需要为它们安装特定的 vite 插件,只需安装预处理器依赖本身即可在项目中直接使用。

  1. 测试 less 是否生效,以及 css module

在 vue 开发中,为防止各个组件间样式污染通常需要给组件设置局部生效的样式。

  • 在 .vue 单文件中使用:
  1. <style scoped lang="less">
  2. .header {
  3. font-size: 36px;
  4. font-weight: bold;
  5. }
  6. </style>
  • 在 .tsx 文件中使用:在样式文件后缀名前加上 .module(index.module.less),在tsx中导入该样式使用。
  1. import classes from "./tsx.module.less"
  2. const FcNode: FC<{ data: number }> = ({ data }) => {
  3. return (
  4. <>
  5. <hr />
  6. <div class={classes['son-header']}>子组件:
  7. {data < 10 ? <span>{data}</span> : <h1>{data}</h1>}
  8. </div>
  9. </>
  10. )
  11. };

至此,可在项目中正常使用 less 语法。

6. 样式统一引入

  • 创建src/styles/reset.less文件,清除默认样式。
  • 创建src/styles/index.less文件,作为统一的样式管理,同时可以编写一些全局样式。
  1. @import "./reset.less";
  2. /* Global css */
  3. #app {
  4. font-family: Avenir, Helvetica, Arial, sans-serif;
  5. -webkit-font-smoothing: antialiased;
  6. -moz-osx-font-smoothing: grayscale;
  7. color: #2c3e50;
  8. width: 100%;
  9. height: 100%;
  10. }
  • main.ts中引入src/styles/index.less

7. ElementUI 的安装和使用

文档:https://element-plus.org/zh-CN/

  1. 安装
  1. yarn add element-plus
  1. 以插件的形式按需引入 ElementUI
  • 创建scr/plugins/element-plus.ts插件,以引入 Button 组件为例:
  1. import { createApp } from "vue";
  2. // 引入样式
  3. import "element-plus/dist/index.css";
  4. // 按需引入组件
  5. import { ElButton, ElMessage } from "element-plus";
  6. export default function loadComponent(app: ReturnType<typeof createApp>) {
  7. // 注册组件
  8. app.use(ElButton);
  9. app.config.globalProperties.$message = ElMessage;
  10. }
  • 创建scr/plugins/index.ts文件,便于统一引入插件:
  1. import { createApp } from 'vue'
  2. import elementPlugin from "./element-plus";
  3. /**
  4. * @description 加载所有 Plugins
  5. * @param {ReturnType<typeofcreateApp>} app 整个应用的实例
  6. */
  7. export function loadAllPlugins(app: ReturnType<typeof createApp>) {
  8. elementPlugin(app)
  9. }
  • src/main.ts文件中加载所有插件:
  1. import { createApp } from "vue";
  2. import App from "./App.vue";
  3. import { loadAllPlugins } from "./plugins";
  4. import router from "./router";
  5. // 应用实例
  6. const app = createApp(App)
  7. // 加载所有插件
  8. loadAllPlugins(app)
  9. app.use(router).mount("#app");
  • 在页面中使用:
  1. <template>
  2. <div class="header">
  3. <el-button>my button</el-button>
  4. </div>
  5. </template>

8. vite 配置路径别名

为了方便复用代码,习惯配置路径别名设置为@,具体配置如下:

  • vite.config.ts文件中配置:
  1. export default defineConfig({
  2. resolve: {
  3. alias: {
  4. "@": path.resolve(__dirname, "src"),
  5. },
  6. }
  7. });
  • tsconfig.json中配置
  1. "compilerOptions": {
  2. "paths": {
  3. "@/*": ["./src/*"]
  4. }
  5. },
  • 在页面中引用
  1. import TsxDemo from "@/components/TsxDemo"

(PS: 配置完成后重启下项目)

9. i18n 配置多语言

  1. 安装 vue-i18n
  1. yarn add vue-i18n@next
  1. 创建多语言src/locale/zh-cn.ts语言文件,src/locale/ja.ts语言文件,再创建src/locale/index文件统一引入语言文件:
  1. import Keys from "@/constant/key";
  2. import { createI18n } from "vue-i18n";
  3. import localeLangJa from "./ja";
  4. import localeLangZhCn from "./zh-cn";
  5. const messages = {
  6. "zh-cn": {
  7. ...localeLangZhCn,
  8. },
  9. ja: {
  10. ...localeLangJa,
  11. },
  12. };
  13. export const getLocale = () => {
  14. // 先寻找缓存里的lang
  15. const localLanguage = window.localStorage.getItem(Keys.languageKey);
  16. if (localLanguage) {
  17. return localLanguage;
  18. }
  19. // 如果缓存没有设置lang,根据所在地查询配置并显示对应lang
  20. const language = navigator.language.toLowerCase();
  21. const locales = Object.keys(messages);
  22. for (const locale of locales) {
  23. if (language.indexOf(locale) > -1) {
  24. return locale;
  25. }
  26. }
  27. // 没有对应的语言配置,显示默认语言
  28. return "ja";
  29. };
  30. const i18n = createI18n({
  31. // 设置地区
  32. locale: getLocale(),
  33. // 设置地区信息
  34. messages,
  35. });
  36. export default i18n;
  1. 结合 ElementUI 组件库,配置多语言

在 App.vue 文件中注入全局多语言配置:

  1. <template>
  2. <el-config-provider :locale="locale">
  3. <router-view />
  4. </el-config-provider>
  5. </template>
  6. <script setup lang="ts">
  7. import { ref } from 'vue';
  8. import { getLocale } from "@/locale"
  9. /** 配置默认语言 */
  10. const locale = ref<string>(getLocale())
  11. </script>
  1. 使用语法:$t(“key”)

10. 设计系统的 Layout UI

根据需求,需要一个基本布局页 Layout,便于元素的复用和一些需要统一处理的操作。