搭建Vue3 后台管理框架 —— 构建路由 封装AXIOS 构建Stores基础

声明本文章只是自己搭建后台框架得一个笔记,不作为任何项目搭建指南,大家看着乐呵乐呵就行。

往期

# 搭建Vue3 后台管理框架 —— 项目创建

# 搭建Vue3 后台管理框架 —— 登录页面

前言

最近事多,都是抽点空余时间写一写,从开始写到现在,一点一点的构架,也算是把基础从新巩固一遍,同时也把相关技术多熟悉熟悉,技术一直在更新,学习永不停止。

构建路由

index.js 路由配置

import { createRouter, createWebHistory } from "vue-router";
import routers from "./module/public";
import NProgress from 'nprogress';
import { USER_TOKEN } from "../utils/LocalDateName";
import { getStorage } from "../utils/PublicFunction";

const onAuthPage = ["/login"];

// 页面加载 进度条
NProgress.configure({
  showSpinner: false, // true 开启loading false 关闭
});

const router = createRouter({
  history: createWebHistory(), // hash模式:createWebHashHistory,history模式:createWebHistory
  scrollBehavior(to, from, savedPosition) {
    return savedPosition ? savedPosition : { left: 0, top: 0 };  // 页面初始化保留位置
  },
  routes: routers
});

// 创建路由守卫
router.beforeEach((to, from, next) => {
  // 开启 进度条
  NProgress.start()
  // 当前路由 不为登录页面 且 没有token  回退到登录页面
  if (!onAuthPage.includes(to.path) && !getStorage(USER_TOKEN)) {
    next({ path: "/login", replace: true });
  } else {
    next();
  }
});

router.afterEach((to)=>{
  // 关闭 进度条
  NProgress.done();
})

export default router;

public.js 这个文件存放公共路由 登录 404 等等

export  default [
  {
    path: '/login',
    name: 'login',
    meta: {
      icon: '',
      title: '登录',
    },
    component:() => import('../views/login/Login.vue')
  }
]

关于module 是用来存放所有的路由文件

关于nprogress 是一个前端页面加载进度条一个小装饰

nprogress官方

目录结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wxGffG1b-1661763090388)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/262d48ceb3784c37970858bb8c61c3f3~tplv-k3u1fbpfcp-watermark.image?)]

构建权限Stores

userStores.js 获取用户信息 按钮权限 存储起来

import { defineStore } from "pinia";
import { USER_AUTH, USER_INFO, USER_TOKEN } from "../utils/LocalDateName";
import { getStorage, setStorage, removeStorage } from "../utils/PublicFunction";
import { useMenuStore } from './menuStore'
export const userInfoStore = defineStore("userInfoStore", {
  state: () => ({
    userInfo: getStorage(USER_INFO) || {},    // 用户信息
    userToken: getStorage(USER_TOKEN) || "", // 用户token
    userAuth: getStorage(USER_AUTH) || []   // 权限菜单
  }),
  getters: {
    //  判断用户是否登录
    isLogin: state => Object.keys(state.userInfo).length > 0
  },
  actions: {
    //  设置用户登录信息
    setUserInfo(payload) {
      if (payload.user) {
        setStorage(USER_INFO, payload.user);
        this.userInfo = payload.user;
      }
      if (payload.token) {
        setStorage(USER_TOKEN, payload.token);
        this.userToken = payload.token;
      }
    },
    // 设置操作颗粒度权限
    setUserAuth(payload) {
      if (payload.auth) {
        setStorage(USER_AUTH, payload.auth);
        this.userAuth = payload.auth;
      }
    },
    //  退出登录清空权限
    LoginOut(){
      removeStorage(USER_TOKEN)
      removeStorage(USER_INFO)
      removeStorage(USER_TOKEN)
      this.userInfo = {}
      useMenuStore.setFunctionMenu([])
    }
  }
});

menuStores.js 获取功能权限菜单 也就是路由权限

import { defineStore } from "pinia";
import { USER_MENU } from "../utils/LocalDateName";
import { setStorage } from "../utils/PublicFunction";

export const useMenuStore = defineStore("userMenuStore", {
  state: () => ({
    userMenu: getStorage(USER_MENU) || [] // 功能权限菜单
  }),
  getters: {},
  actions: {
    //  获取路由权限菜单
    async getFunctionMenu() {
      // 请求功能接口  这里请求接口 获取data
      setStorage(USER_MENU, data);
    },
    // 设置
    setFunctionMenu(payload){
      this.userMenu = payload
    }
  }
});

目录结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ixwTiGI-1661763090390)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cf3eece38b7942f9af0a09ed3d9de787~tplv-k3u1fbpfcp-watermark.image?)]

封装axios

axios 关于axios封装 真的可以说全网满天飞 这里只代表个人想法 肯定有不足得地方

import axios from "axios";
import router from '@/router'
import { message, Modal } from 'ant-design-vue';
import { getStorage } from "./PublicFunction";
import { userInfoStore } from '@/stores/userStores'
class HttpRequest {
  static getInsideConfig() {       // 设置请求头
    return {
      headers: { "X-Requested-With": "XMLHttpRequest" }  // X-Requested-With : null (返回为文本) XMLHttpRequest (返回JSON格式)
    };
  };

  intercetors(instance) {
    //  设置请求拦截   添加token
    instance.interceptors.request.use((config)=>{
      if(config.url.includes('company-console')){  // 判断请求地址
        const authToken = getStorage('USER_TOKEN')     // 获取本地存储token
        authToken && (config.headers['xh-token'] = authToken)   // 请求头添加token
      }
      return config
    }, error => {
      return Promise.reject(error)
    })

    // 响应拦截
    instance.interceptors.response.use((response)=>{
      if(response.config.url.includes('company-console') && !response.config.url.includes('export') && !response.config.url.includes('download')){
        if([401,202].includes(response.data.code)){
          userInfoStore.LoginOut()
          router.replace({path:'/login'})
        }

        if(response.data.code && response.data.code !== 401 && response.data.code !== 202){
          modal = Modal.error({
            title: '错误提示',
            content: response.data.msg,
            centered: true
          });
        }
        if(response.data.code && response.data.code == 202){
          message.warning({
            content: response.data.msg,
            onClose: () => {
              userInfoStore.LoginOut()
              router.replace({ path: '/login' });
            },
          });
        }

      }
      return response.data
    },error => {

      const { status } = error.response
      if(status === 401){
        userInfoStore.LoginOut()
        router.replace({ path: '/login' });
      }
      return Promise.reject(error)
    })

  };
  request(options) {
    const instance = axios.create();
    options = Object.assign({}, HttpRequest.getInsideConfig(), options);
    this.intercetors(instance);
    return instance(options);
  }

}

const httpRequest = new HttpRequest();
export default httpRequest;

目录结构

LocalDateName.js || PublicFunction.js 这个两个文件 传送门可以获取到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1JbI7SD-1661763090391)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b8506f982dac4eccac644c7c0bb4b67f~tplv-k3u1fbpfcp-watermark.image?)]

结尾

经过这么多天(零碎得时间),才写了这点东西,而且觉得很多地方还需要打磨,暂时想法是先把大体框架打起来然后一点一点打磨吧,现在最大得问题是后端怎么办(后端我不会啊),还在纠结是用前端server实现还是使用后端java技术(后端需要自学)各位jym有什么好的建议。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值