约定式路由

303 阅读1分钟

前言

前端开发中,讲究的是一个 约定大于配置,这样能使得我们可以减少一些重复的代码,提高开发效率;以下是根据 多级目录 生成的 多级路由

技术选型:vite、vue3、vue-Route4、Typescript

提示:在 vue2 中,需要引入多个文件时,通过 require.context 来完成。而 vite 则需要通过 import.meta.glob来完成

在项目中,我是这样规定自己的文件结构

  • 文件结构

image.png

  • views 文件夹下包含了 index.vue、page.ts 以及 404、about、home等文件夹
  • 重点:这些文件夹下都包含着 page.ts。该 page.ts 主要作用是配置 meta 里面的一些信息(根据自己需求),如下

image.png

重中之重

  • 如果没有 page.ts 则不展示新增的页面,并且跳转到 404 页面

代码分析

  • 在 router 的 index.ts 中,通过 import.meta.glob 获取多个文件(page.ts、index.vue)
const pages = import.meta.glob('../views/**/page.ts', {
  eager: true, 
  import: 'default' 
}) // 所有page.ts

const pageComps = import.meta.glob('../views/**/index.vue') // 所有index.vue

eager、import 没配置之前,打印出来是以函数的形式

image.png

配置之后

image.png

  • 获取到 pages.ts 进行遍历
const comRoute = Object.entries(pages).map(([path, meta]) => {
  const comJsPath = path; // 动态导入组件路径
  let comPath = comJsPath.replace('page.ts','index.vue')
  
  const regex = /views\/(.*?)\/page\.ts/;
  const match = path.match(regex); // 去掉../
  let extracted = match ? match[1] : ""; // 获取文件夹名称,作为路由路径
  
  let name = "";
  if(extracted.indexOf('children') > -1) {
    name = extracted.replace(/\//g, "-");
  } // 路由名称 (该判断可不写,可以直接使用 extracted)

  return {
    name,
    path: `/${extracted}`, 
    component: pageComps[comPath], // 通过 import.meta.glob 获取所有 index.vue;  映射出对应的组件
    meta,
  }
})

完整代码

import { createRouter, createWebHistory } from 'vue-router'

const pages = import.meta.glob('../views/**/page.ts', {
  eager: true,
  import: 'default'
})

const pageComps = import.meta.glob('../views/**/index.vue')

const comRoute = Object.entries(pages).map(([path, meta]) => {
  const comJsPath = path;
  let comPath = comJsPath.replace('page.ts','index.vue')

  const regex = /views\/(.*?)\/page\.ts/;
  const match = path.match(regex);
  let extracted = match ? match[1] : "";

  let name = "";
  if(extracted.indexOf('children') > -1) {
    name = extracted.replace(/\//g, "-");
  }

  return {
    name,
    path: `/${extracted}`, 
    component: pageComps[comPath],
    meta,
  }
})

const routers = comRoute as any;

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    ...routers,
    {
      path: '/:pathMatch(.*)*',
      redirect: '/404'
    } // 文件路径不存在,跳转到404 
  ]
})

export default router