vue3 pinia admin开发日志

初始化项目
// 使用 npm
npm create vite
// 使用yarn
yarn create vite
// 使用pnpm
pnpm create vite创建完成后进入项目文件夹安装依赖
// 使用 npm
npm install
// 使用yarn
yarn install
// 使用pnpm
pnpm install
接下来清空项目



vscode插件准备

配置项目
配置别名
为src配置一个别名,避免开发过程中使用 ./ ../ 之类的形式引用。
在项目根目录的 vite.config.js 中添加 alias

环境变量
在项目根目录创建.env文件,以便后续使用通过import.meta.env的形式使用
VITE_BASE_URL= /
VITE_HISTORY_ROUTER="hash"安装vue-router 、pinia和axios

创建文件夹
将 src 下的文件夹结构改成如下图所示

src
|----api //接口封装
|----assets //引入资源
|----components //二次封装组件
|----directives //自定义指令
|----layout //公共组件
|----plugins //插件
|----router //路由
|----store //状态管理
|----style //样式
|----utils //工具函数
|----views //页面创建配置文件
在项目根目录有个 public 文件夹,这是在这个文件夹内的文件不会被打包,所以我们要在这里放个文件,来实现前端更新时通知客户端刷新浏览器
// serverConfig.json
{
"Version": "0.0.1"
}除了Version版本号以外,可以包含其他字段。这些字段将在vue初始化之前被读取
获取配置
在vue初始化之前获取配置内容,因此,我们需要一个工具函数

然后对 main.ts中初始化流程进行更改

注册pinia
在@/store/index.ts中
import { createPinia } from "pinia";
const store = createPinia();
export { store };然后在main.ts 中引入并注册 store

使用pinia
store/modules/app.ts 举例
import { defineStore } from "pinia";
import { store } from "@/store";
type appType = {
routes: Array<{
path: string;
name: string;
meta: { showLink?: boolean; title?: string };
children?: Array<any>;
}>;
};
export const useAppStore = defineStore({
id: "app",
state: (): appType => ({
routes: [],
}),
actions: {
SET_ROUTES(routes: Array<any>) {
this.routes.length = 0;
routes.forEach((value) => {
this.routes.push(value);
});
},
ADD_ROUTES(routes: Array<any>) {
routes.forEach((value) => {
this.routes.push(value);
});
},
},
});
export function useAppStoreHook() {
return useAppStore(store);
}
在vue组件外使用时调用 useAppStoreHook钩子函数,在vue组件内则直接使用useAppStore
注册vue-router
router/index.ts
import { createWebHashHistory, createWebHistory } from "vue-router";
import { asyncRoutes } from "./routes";
const whiteList = ["/login"];//添加登录页到白名单
const routes = asyncRoutes;
const router = createRouter({
history:
import.meta.env.HISTORY_MODE === "hash"
? createWebHashHistory()
: createWebHistory(),
routes,
strict: true,
});
export default router;引入路由
router/routes/index.ts
import basicRoute from "./basic";
import {
ascending,
buildHierarchyTree,
formatTwoStageRoutes,
formatFlatteningRoutes,
} from "@/utils";
import { useAppStoreHook } from "@/store/modules/app";
import type { RouteRecordRaw, RouteComponent } from "vue-router";
/**
* 自动导入静态路由
*/
const modules: Record<string, any> = import.meta.glob(["./modules/**/*.ts"], {
eager: true,
});
const routerModuleList: any[] = [];
Object.keys(modules).forEach((key) => {
const mod = modules[key].default || {};
const modList = Array.isArray(mod) ? [...mod] : [mod];
routerModuleList.push(...modList);
});
export const constantRoutes: Array<RouteRecordRaw> = formatTwoStageRoutes(
formatFlatteningRoutes(buildHierarchyTree(ascending(routerModuleList)))
);
/** 用于渲染菜单,保持原始层级 */
export const constantMenus: Array<RouteComponent> = ascending(
routerModuleList
).concat(...basicRoute);
useAppStoreHook().SET_ROUTES(constantMenus);
export const asyncRoutes = [...constantRoutes, ...basicRoute];
router/routes/basic.ts基础路由
export default [
{
path: "/login",
name: "Login",
component: () => import("@/views/login/login.vue"),
meta: {
title: "login",
showLink: false,
rank: 101,
},
},
{
path: "/redirect",
component: () => import("@/layout/index.vue"),
meta: {
title: "home",
showLink: false,
rank: 102,
},
children: [
{
path: "/redirect/:path(.*)",
name: "Redirect",
component: () => import("@/layout/redirect.vue"),
},
],
},
{
path: "/empty",
name: "Empty",
component: () => import("@/views/empty/empty.vue"),
meta: {
title: "empty",
showLink: false,
rank: 103,
},
},
];
router/routes/modules/home.ts 主页路由
import Home from "@/layout/index.vue";
export default {
path: "/",
name: "Home",
component: Home,
meta: {
title: "首页",
showLink: true,
rank: 0,
},
redirect: "/welcome",
children: [
{
path: "/welcome",
name: "Welcome",
component: () => import("@/views/home/welcome/welcome.vue"),
meta: {
title: "首页",
},
},
{
path: "/dashboard",
name: "Dashboard",
component: () => import("@/views/home/dashboard/dashboard.vue"),
meta: {
title: "看板",
},
},
{
path: "/workbench",
name: "Workbench",
component: () => import("@/views/home/workbench/workbench.vue"),
meta: {
title: "工作台",
},
},
],
} as routerConfig;
配置自动引入与自动注册
安装依赖
npm i -D unplugin-auto-import unplugin-icons unplugin-vue-components在vite.config.ts中引入
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import Icons from "unplugin-icons/vite";
import IconsResolver from "unplugin-icons/resolver";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
export default defineConfig(({ mode }) => {
return {
plugins:[
AutoImport({//自动引入
dts:"types/auto-import.d.ts"//声明文件输出位置
resolvers:[
ElementPlusResolver(),
IconResolver({
prefix:"Icon"
}),
imports:["vue","vue-router"]//需要全局引入的包
]
}),
Components({//自动注册
dts: "types/components.d.ts",//声明文件输出位置
resolvers: [
ElementPlusResolver(),
IconsResolver({ enabledCollections: ["ep"] }),
],
}),
Icons({// 引入图标
autoInstall: true,
}),
]
}css预处理器
vue脚手架默认支持css预处理器,只需引入即可使用
使用何种预处理器一般取决于组件库的css预处理器
原子化css
什么是原子化css
原子化 CSS(Atomic CSS):
原子化 CSS 是一种 CSS 的架构方式,它倾向于小巧且用途单一的 class,并且会以视觉效果进行命名;有些人可能会称其为函数式 CSS,或者 CSS 实用工具。本质上,可以将原子化的 CSS 框架理解为这类 CSS 的统称
相关框架
tailwindcss
windicss
unicss


