重新新建一个vue3项目

从头搭建一个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);
相关推荐
北海-cherish19 分钟前
Wouter 和 React Router的区别
前端·react.js·前端框架
醉方休21 分钟前
TensorFlow.js高级功能
javascript·人工智能·tensorflow
郝学胜-神的一滴28 分钟前
深入理解前端 Axios 框架:特性、使用场景与最佳实践
开发语言·前端·程序人生·软件工程
炒香菇的书呆子38 分钟前
基于Amazon S3设置AWS Transfer Family Web 应用程序
javascript·aws
!chen1 小时前
学习 React 前掌握 JavaScript 核心概念
javascript·学习·react.js
笨笨狗吞噬者1 小时前
【uniapp】小程序端实现分包异步化
前端·微信小程序·uni-app
Filotimo_1 小时前
2.CSS3.(1).html
前端·css
YAY_tyy1 小时前
【JavaScript 性能优化实战】第五篇:运行时性能优化进阶(懒加载 + 预加载 + 资源优先级)
前端·javascript·性能优化
1024小神1 小时前
flutter 使用dio发送本地https请求报错
前端
正义的大古2 小时前
OpenLayers地图交互 -- 章节七:指针交互详解
前端·javascript·vue.js·openlayers