开发记录 从零开始开发后台管理系统,还是有很多值得记录的地方。构建工具Vite、使用Vue3。

1.批量导入指定目录的组件 /*

  • @author 友人a丶
  • @date 2022-07-11
  • @app Vue应用对象
  • / export default function (app) { /
    • 指定要导入的文件目录
    • 直接加载用{eager:true},懒加载用glob
    • / const modules = import.meta.glob([‘@/layouts//index.js’, ‘@/components//index.js’]); for (let i in modules) { let name = /(.)?\/(.*)\/index.js/.exec(i); /直接引入组件/ app.component(name[2], modules[i].default); /异步组件/ app.component(name[2], defineAsyncComponent(modules[i])); } }

直接加载的时候modules就是元素为组件对象的数组,懒加载的时候是元素为import方法的函数数组 。

2.应用初始化 /*

  • @author 友人a丶
  • @date 2022-07-11 *
  • 引导系统初始化
  • 初始化全局响应拦截器
  • 初始化路由守卫
  • 初始化用户登录
  • / import loadGuard from “./loadGuard” import loadInterceptor from “./loadInterceptor” import watchRem from “./watchRem”; export default async function (){ /
    • 自动调整rem
    • / watchRem(); /
    • 加载拦截器
    • / loadInterceptor(); /
    • 加载路由守卫
    • */ loadGuard(); }

3.自动调整rem /*

  • @author 友人a丶
  • @date 2022-07-11
  • 自动调整rem的大小
  • */ export default function () { let l = () => { let r = document.documentElement, o = r.offsetWidth / 100; o < 16 && (o = 16), r.style.fontSize = o + “px”, window.rem = o }; l(); window.addEventListener(“resize”,()=>l()); }

4.导航守卫 /*

  • @author 友人a丶
  • @date 2022-07-11 *
  • 加载全局路由守卫
  • */ import {router} from “@/router”; import userStore from “@/stores/user”; import load from “@/common/load”; import systems from “@/stores/system”; import NProgress from ‘nprogress’ import loadUser from “@/service/loadUser”; /进度条/ NProgress.configure({showSpinner: false}) // 不需要拦截的路由配置 const ignoreRoute = { names: [‘404’, ‘403’], //根据路由名称匹配 paths: [‘/login’], //根据路由fullPath匹配 /**
    • 判断路由是否包含在该配置中
    • @param route vue-router 的 route 对象
    • @returns {boolean} / includes(route) { return ignoreRoute.names.includes(route.name) || ignoreRoute.paths.includes(route.path) } } /
  • 加载路由守卫
  • / export default function () { console.log(“加载路由守卫…”); let user = userStore();//全局状态 /
    • 加载进度条
    • / router.beforeEach((to, from, next) => { // start progress bar if (!NProgress.isStarted()) { NProgress.start() } next() }); /
    • 判断系统是否初始化
    • / router.beforeEach(async (to, from, next) => { if(!systems().loaded){ await loadUser();//加载用户信息初始化系统 } next(); //下一个 }); /
    • 已登录时,访问登录页面,让它走
    • / router.beforeEach( (to, from, next) => { if (user.role != 0 && (to.path == “/login”)) { next(‘/’); }else{ next(); //下一个 } }); /
    • 判断是否登录
    • / router.beforeEach((to, from, next) => { /
      • 判断是否需要拦截
      • / console.log(“登录判断守卫激活….”) if (ignoreRoute.includes(to)) { next(); } else { /
        • 角色为0,代表未登录
        • / if (user.role == 0) { next({path: ‘/login’}); } else { next(); } } }) /
    • 判断用户权限
    • / router.beforeEach((to, from, next) => { console.log(“权限判断守卫激活….”) /
      • 判断是否需要拦截
      • / if (ignoreRoute.includes(to)) { next(); } else { /
        • 判断用户权限
        • / if (user.role < to.meta.role) { load.error(“您无权限访问该页面….”); next({path: ‘/403’}); } else { next(); } } }) /
    • 切换页面标题
    • / router.beforeEach((to, from, next) => { document.title = to.name next(); }) /
    • 结束进度条
    • */ router.afterEach(() => { // finish progress bar NProgress.done() }); }

5.axios拦截器  /*

  • @author 友人a丶
  • @date 2022-07-11 *
  • 加载axio拦截器
  • / import axios from “axios”; import load from “@/common/load”; import {router} from “@/router”; import apis from ‘@/service/api’; // 不需要拦截的接口 const ignoreApi = { api: [ apis.login ], includes(api) { / * 判断当前请求的接口是否在忽略的列表 * / for(let item of ignoreApi.api){ let reg=new RegExp(.*${item}.*); if(reg.test(api)){ return true; } } return false; } } /
  • 注册响应拦截器
  • / export default function (){ console.log(“加载拦截器…”); axios.interceptors.response.use(function (res){ console.log(“请求接口:”+res.config.url) console.log(res); / * 判断是否需要拦截 * / if(ignoreApi.includes(res.config.url)){ return res; } / * 判断用户登录是否失效 * */ if(res.code == -1){ load.confirm(“当前登录状态已失效,请您重新登录!”,()=>{ router.replace(‘/login’) }) } return res; }); }

6.获取某个路由的子路由(用于生成菜单) /*

  • 操作路由的相关方法
  • / import {router} from “@/router/index”; /
  • 获取某个路由项的子项
  • */ export function getChildren(path) { let routes=router.getRoutes(); for (let i of routes) { if (i.path == path) { return i.children; } } }

7.简单的弹出封装(antd design vue) import {

message,
Modal

} from “ant-design-vue”; let hide = []; export default {

loading(text = '加载中...') {
	hide.push(message.loading(text, 0))
},
loaded() {
	if (hide.length > 0) {
		let timer=setTimeout(()=>{
			hide[hide.length - 1]()
			hide.splice(hide.length - 1, 1)
		},500);
	}
},
error(text = '加载异常') {
	message.error(text);
},
success(text = 'ok!') {
	message.success(text);
},
confirm(text, callback = null) {
	Modal.confirm({
		title: '提示',
		centered: true,
		content: text,
		maskClosable: false,
		onOk: (close) => {
			close(); //关闭
			if (callback) {
				callback()
			}
		}
	})
}

}

8.退出登录 /*

  • @author 友人a丶
  • @date 2022-07-11
  • 用户退出登录
  • / import user from “@/stores/user”; import Cookies from “js-cookie”; import {router} from “@/router”; import load from “@/common/load”; export default function () { load.confirm(“确认退出登录吗?”,()=>{ user().$reset(); //重置用户数据的状态管理器 / * 清空cookie * / Object.keys(Cookies.get()).forEach((item)=>{ Cookies.remove(item); }) / * 跳转登录界面 * / router.replace(‘/login’); }) } 9.获取需要缓存的组件列表 /
  • @author 友人a丶
  • @date 2022-07-11
  • name代表组件名
  • 获取需要缓存的组件
  • / import routes from ‘@/router’ export function getChached(path=‘’) { let routes=router.getRoutes(); let cahced=[]; //是否开启缓存 /
    • 为空代表获取所有一级组件
    • */ if(path == “”){ routes.forEach((item)=>{ if(item.meta.cache){ cahced.push(item.meta.cache); } }); }else{ /遍历目标子组件/ for (let i of routes) { if (i.path == path) { i.children.forEach((item)=>{ if(item.meta.cache){ cahced.push(item.meta.cache); } }); } } } return cahced; }

需要考虑 1.如何让显示的菜单响应路由的变化(跳转到某个页面,自动选中某个菜单)? 本身菜单被点击了,自己会变化被选中的状态,需要考虑的是从其他页面跳转过来的时候,如何正常匹配显示被选的菜单;

路由包括静态的路由和有变化的参数路由,某些情况下还会具有参数。

let selectedKeys = computed({

  get() {
    let current = route.fullPath;

for (let i = 0; i < items.length; i++) {

      //断言右边是空或者?或者/
      // 完整匹配或者带参数匹配
      let regexp=new RegExp(`(?:.*${items[i].path}$)|(?:.*${items[i].path}[\?\/].*)`);
      if(regexp.test(current)){
        return [i];
      }
    }
  },
  set(value) {
    return;
  }
}

);

2.如何组织目录?

代表页面的组件一般以文件夹的形式通过index.js导出组件,方便观察层次结构,并且页面组件一般都会拆分JS模块,通过文件夹也更加方便文件的分类,保持目录的简洁。 其他的组件,如果设计到大量的逻辑,需要拆分JS模块,可以用文件夹,如何很简单的直接用.vue文件即可。 如何让父子组件的层级更加清晰?首先名字可以按层级写;parent-children.vue。 名字较长的组件用“-”分割,更加友好。

3.结构型的组件划分?

将布局看组架子(布局组件)、视图看做需要的内容(视图组件),布局承载内容; 通过全局状态的设置来动态调整布局组件的显示和隐藏。

4.如何组织无限层级的子路由作为菜单? 模板方式实现起来非常的麻烦,JSX的方式更加适合这种需求;

首先需要根据当前路由获取一个可以作为祖先的父级路由对象

5.运行中的router getRoutes(); 不管是push、redirect、route-link,都可以进行相对路径(dynamic)或者绝对路径(/dynamic)跳转;

[

{
    "path": "/spread/tencent",
    "name": "腾讯广告",
    "meta": {
        "role": 0,
        "icon": "icon-guangdiantong"
    },
    "props": {
        "default": false
    },
    "children": [],
    "instances": {},
    "leaveGuards": {},
    "updateGuards": {},
    "enterCallbacks": {},
    "components": {}
}

]

阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。