从头搭建一个vue3项目 记录一下自己的遇到的问题以及记录一下自己的学到的东西
栽一棵树最好的时间是现在。
PS:怕作者哪天把文章删了,所以就把自己写的步骤都copy下来了。
参考文章:Vue3+ Vite + Element-Plus + TypeScript 从0到1搭建企业级后台管理系统
新建项目
js
//查询node版本
node -v // 16.17.0
npm -v //8.15.0
Axios
遇到的问题

解决办法:
在tsconfig.json中加入
js
{
"compilerOptions": {
// 加入下面这三行代码是为了使import
"module": "esnext",
"target": "es5", // 或其他目标版本
"outDir": "./dist",
}
}
路由vue-router
安装vue-router
js
npm install vue-router@next
创建路由
新建
src/router/index.ts
js
// src/router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw ,createWebHistory } from 'vue-router';
export const Layout = () => import('@/layout/index.vue');
// 静态路由
export const constantRoutes: RouteRecordRaw[] = [
{
path: '/redirect',
component: Layout,
meta: { hidden: true },
children: [
{
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index.vue')
}
]
},
{
path: '/login',
component: () => import('@/views/login/index.vue'),
meta: { hidden: true }
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index.vue'),
name: 'Dashboard',
meta: { title: 'dashboard', icon: 'homepage', affix: true }
}
]
}
];
/**
* 创建路由
*/
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes as RouteRecordRaw[],
// 刷新时,滚动条位置还原
scrollBehavior: () => ({ left: 0, top: 0 })
});
/**
* 重置路由
*/
export function resetRouter() {
router.replace({ path: '/login' });
location.reload();
}
export default router;
全局注册
js
//引入路由
import router from "@/router";
import App from './App.vue'
createApp(App).use(router).mount('#app')
路由守卫
js
//路由守卫
import type { RouteRecordRaw } from "vue-router";
import NProgress from "@/utils/nprogress";
import router from "@/router";
import { useUserStoreHook, useUserStore } from "@/store";
// 储存键值对的地方
import { ROLE_ROOT } from "@/constants";
export function setupPermission() {
const whiteList = ["/login"]; // 无需登录的页面
router.beforeEach(async (to, from, next) => {
NProgress.start();
console.log(to);
try {
// 在这里这两个的区别是什么啊 啊啊啊
console.log("===", useUserStoreHook().isLoggedIn);
console.log("===", useUserStore().isLoggedIn);
console.log(whiteList.includes(to.path));
// 使用 store 暴露的登录态,便于后续扩展(如基于过期时间等)
const isLoggedIn = useUserStore().isLoggedIn;
// 未登录处理
if (!isLoggedIn) {
if (whiteList.includes(to.path)) {
next();
} else {
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`);
NProgress.done();
}
return;
}
// 已登录且访问登录页,重定向到首页
if (to.path === "/login") {
next({ path: "/" });
return;
}
// 已登录用户的正常访问
// const permissionStore = usePermissionStore();
// const userStore = useUserStore();
// 路由未生成则生成
// if (!permissionStore.isDynamicRoutesGenerated) {
// if (!userStore.userInfo?.roles?.length) {
// await userStore.getUserInfo();
// }
// const dynamicRoutes = await permissionStore.generateRoutes();
// dynamicRoutes.forEach((route: RouteRecordRaw) => {
// router.addRoute(route);
// });
// next({ ...to, replace: true });
// return;
// }
// 检查路由是否存在
if (to.matched.length === 0) {
next("/404");
return;
}
// 设置页面标题
const title = (to.params.title as string) || (to.query.title as string);
if (title) {
to.meta.title = title;
}
next();
} catch (error) {
console.error("❌ Route guard error:", error);
// 出错时清理状态并重定向到登录页
// try {
// await useUserStore().resetAllState();
// } catch (resetError) {
// console.error("❌ Failed to reset user state:", resetError);
// }
next("/login");
NProgress.done();
}
});
router.afterEach(() => {
NProgress.done();
});
}
setupPermission();
/** 判断是否有权限 */
export function hasAuth(
value: string | string[],
type: "button" | "role" = "button"
) {
const { roles, perms } = useUserStore().userInfo;
// 超级管理员 拥有所有权限
if (type === "button" && roles.includes(ROLE_ROOT)) {
return true;
}
const auths = type === "button" ? perms : roles;
return typeof value === "string"
? auths.includes(value)
: value.some((perm) => auths.includes(perm));
}
自定义指令

案例
新建一个directive / highlight /index.ts
js
// 自定义指令
import type { Directive } from "vue";
export const highlight: Directive = {
mounted: (el) =>{
console.log('elel',el);
return el.classList.add("is-highlight")
},
};
新建 directive/ index.ts
js
import { App } from "vue";
import { highlight } from "./permission";
// 注册一个全局自定义指令 `v-highlight`
export function setDirectiveFn(app: App<Element>) {
app.directive("highlight", highlight);
}
在main.ts
中注册
js
import {setDirectiveFn} from "@/directive";
setDirectiveFn(app);