vite+vue3+typescript+vuex+vue-router+element-plus构建管理系统前端架构
一、使用vite初始化
我这里是使用yarn包管理工具安装,使用npm或者pnpm的同理 执行下面shell命令创建一个新的项目模板
yarn create vite 项目名称 --template vue-ts
创建成功后我们使用vscode编辑器打开项目,其中目录结构如下图:

此时我们执行yarn install安装所需要的依赖包,安装完必执行yarn dev会打开vite+vue的欢迎界面
二、配置eslint,prettier
1:eslint初始化
// 执行下面命令
eslint --init
按照提示我们依次选择以下几个主要选项
? How would you like to use ESLint? ...
To check syntax only
To check syntax and find problems
> To check syntax, find problems, and enforce code style
? What type of modules does your project use? ...
> JavaScript modules (import/export)
CommonJS (require/exports)
None of these
? Which framework does your project use? ...
React
> Vue.js
None of these
? Does your project use TypeScript? » No / Yes
选择推荐风格,这里我们直接选第一个跟着引导去选择aribn或者standard
> Use a popular style guide
Answer questions about your style
Inspect your JavaScript file(s)
选择完后,需要安装一些eslint相关的依赖包,默认是用npm安装,安装完会自动生成一个eslintrc.js,内容如下
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-essential",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"overrides": [
],
"parser": "vue-eslint-parser",
"parserOptions": {
"ecmaVersion": "latest",
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"plugins": [
"vue",
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/ban-types": [
"error",
{
"extendDefaults": true,
"types": {
"{}": false
}
}
],
"vue/multi-word-component-names":"off"
}
}
创建.eslintignore文件,忽略eslint不需要检查的文件
/index.html
/lambda/
/scripts
/config
/plugins
.history
/tsconfig.json
/src/vite-env.d.ts
2:配置prettier
安装prettier
yarn add prettier -D
解决 eslint 和 prettier 冲突
安装 eslint-config-prettier
解决 ESLint
中的样式规范和 prettier
中样式规范的冲突
,以 prettier
的样式规范为准
,使 ESLint 中的样式规范自动失效
eslint-plugin-prettier
eslint-plugin-prettier插件会调用prettier对你的代码风格进行检查,其原理是先使用prettier对你的代码进行格式化,然后与格式化之前的代码进行对比,如果过出现了不一致,这个地方就会被prettier进行标记。
接下来,我们需要在rules中添加,"prettier/prettier": "error"
,表示被prettier标记的地方抛出错误信息。\
//.eslintrc.js
{
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
项目下新建 .prettierrc.json
文件
module.exports = {
tabWidth: 2,
jsxSingleQuote: true,
jsxBracketSameLine: true,
printWidth: 100,
singleQuote: true,
semi: false,
overrides: [
{
files: '*.json',
options: {
printWidth: 200,
},
},
],
arrowParens: 'always',
}
三、配置路径别名,处理import引入时ts报错
在vite-config.ts中添加如下配置
base: './', // 设置打包路径
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
}
在tsconfig.json中增加配置
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
}
此时的@就可以指向我们的src目录了
在src文件夹下创建shims-vue.d.ts文件 添加我们import引入时ts报错的模块
// 例如
declare module 'axios';
declare module 'element-plus';
declare module 'js-cookie';
四、配置element-plus
elementUi的配置非常简单这里我就不说了,直接参考官方的配置指南就可以了 element-plus.gitee.io/zh-CN/guide…
五、配置vuex、vue-route、less开发环境
// 我们一次把所有模块都安装上
yarn add vuex vue-router less less-loader
less使用跟vue2没有区别,安装完loader可以直接在style里面制定lang="less"
1:配置vuex
我们在src目录下创建store文件夹,store文件夹下分别创建index.ts 和modules文件夹,其中modules下面是我们的每个不通的store
因为vuex修改了初始化的方法,这里给vue2使用时略有区别,使用createStore创建store仓库
import { createStore } from 'vuex';
import getters from './getters';
import userStore from './modules/user';
import systemStore from './modules/system';
import permissionStore from './modules/permission';
const storeObj: any = {
modules: {
user: userStore,
system: systemStore,
permission: permissionStore,
},
getters,
};
export default createStore(storeObj);
ps:我这里分别引入了三个store,还可以使用import.meta.globEager引入所有的文件,写个通用函数来解析最好,因为vite中乜有require,这个功能既类似于require.context
配置完以上回到src/main.ts中,引入store
挂在store
import store from './store';
app.use(store)
2:配置vue-router
在src文件夹下创建router文件夹
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
const constantRoutes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'layout',
component: () => import('@/pages/layout/index.vue'),
},
{
path: '/login',
name: 'login',
component: () => import('@/pages/login/index.vue'),
},
{
path: '/404',
name: '404',
component: () => import('@/pages/error-page/404.vue'),
},
];
// 权限用动态路由添加
export const asyncRoutes: any = [];
export const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
});
// 权限用动态路由移除
export function resetRouter() {
asyncRoutes.forEach((route: any) => {
router.removeRoute(route.name);
});
}
回到main.ts,仍然是引入挂载
import router from './router';
app.use(router)
这里到了重点权限控制,我这里使用动态路由控制权限
// 角色权限,动态路由
const whiteList = ['/login', '/404'];
let pageRefresh = true;
router.beforeEach(async (to, from) => {
// 如果是login或者404页面直接跳转过去
if (whiteList.indexOf(to.path) !== -1) {
if (to.path == '/login') {
pageRefresh = true;
}
return true;
}
// 获取token,如果用户没登录,则跳转登录页面
const token = store.getters.token;
if (!token) {
router.push({
path: 'login',
query: {
redirect: to.path,
},
});
} else {
//如果为true说明已添加过直接跳过
if (!pageRefresh) {
return true;
} else {
//后端获取动态路由
await store
.dispatch('permission/generateRoutes') // 到store下的permission中执行路由添加
.then((res: any) => {
console.log(router.getRoutes());
// 没有子路由时则回首页
if (res && to.matched.length === 0) {
router.push(to.fullPath);
}
});
pageRefresh = false;
}
}
});
import { asyncRoutes, router } from '@/router';
import { RouteRecordRaw } from 'vue-router';
const _modules = import.meta.glob('@/pages/**/*.vue');
/**
* 后台查询的菜单数据拼装成路由格式的数据
* @param routes
*/
export function generaMenu(routes: any, data: any) {
data.forEach((item: any) => {
const menu = {
path: item.path,
component: () => _modules[`/src/pages${item.component}.vue`], // 这里有坑,动态引入的组件无法添加,我尝试了很多方式,最后使用## defineAsyncComponent引入解决的
children: [],
name: item.menuName,
meta: {
title: item.title,
icon: item.icon,
noCache: item.noCache,
},
};
if (item.children) {
generaMenu(menu.children, item.children);
}
routes.push(menu);
});
}
const permission = {
namespaced: true,
state() {
return {
routes: [],
};
},
mutations: {
SET_ROUTES: (state: any, routes: any) => {
state.routes = routes;
},
},
actions: {
generateRoutes({ commit }: any) {
return new Promise((resolve) => {
getRoutes().then((res: any) => {
if (res.code === 200) {
const { data } = res;
const list = data[0].children;
//获取router添加到asyncrouter中
generaMenu(asyncRoutes, list);
console.log('调整好的路由', asyncRoutes);
// 添加路由
asyncRoutes.forEach((itemRouter: RouteRecordRaw) => {
router.addRoute('layout', itemRouter);
});
commit('SET_ROUTES', list);
resolve(list);
} else {
ElMessage.error('菜单数据获取异常');
}
});
});
},
},
};
export default permission;
end:到这里我们基本完成了所有的配置,赶紧尝试一下吧!!!
转载自:https://juejin.cn/post/7152440373393457182