前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开学第一课:如何在vite中打造一个基于文件结构的路由系统

开学第一课:如何在vite中打造一个基于文件结构的路由系统

作者头像
FE情报局
发布2023-09-05 18:26:57
6030
发布2023-09-05 18:26:57
举报
文章被收录于专栏:FE情报局

一个较好的工程模版,不应该被较多的配置束缚住,应该有一个较好的统一约定,采用约定大于配置的

方式,从而减少开发人员被配置束缚,获得简单化的同时又不失去灵活性,省去配置,减少学习成本,在前端工程中,路由配置就是一个比较麻烦的配置,那如何将前端路由系统做一个约定式开发?

通常来说,较好的约定就是文件目录结构就是路由,路由的权限以及额外配置在一个单独的文件中,next 框架就很好的实现了这一方式,他们就是采取的文件路由的方式,又或者 umi 框架,也有约定式路由的配置

通过文件结构自动生成所需要的路由,这种方式简单高效,已经成熟应用于各大框架

那如何在 vite 中实现这个功能?而不是写大量的路由配置,我们新建一个 vite 项目,然后引入 vue-router,react 也可以根据自己的方式引入对应的路由,然后对项目中的路由进行配置

一般来说,项目的路由配置是大量而且繁琐的,我们经常在项目中看到整个一套的 router 的配置,比如这种

当我需要新增一个路由的时候,需要在这个文件中编辑对应的配置,并且为了方便以后的维护,路径和文件夹一般都是一一对应的,当前的文件结构

写这种大量的配置无疑增加了我们的配置负担,而且仔细研究就会发现,这样的配置其实是通用化的,比如都有 path,而 path 和 文件目录是有对应关系的,还有一些自定义属性,包括页面的题目,菜单的顺序,权限等相关内容,或者还有可能存在 icon 之类的配置

既然 path 和文件目录有对应的关系,那我们就可以通过文件夹自动生成这份 router 配置,但是文件夹中的内容有时候可能会涉及到 components,或者一些组件的东西,这部分是不需要被映射的,同时对于一些自定义属性也要增加一些扩展

那有什么好的方式可以将这部分的东西统一收纳管理么?

文件路径可以获取,那如何避免 components 这种文件夹?同时又能够额外的增加一些配置属性呢?

这里我们可以借鉴一下微信小程序的做法,小程序是有一个 app.json 的文件,里面包含了所有页面的配置

但是我们可以针对每个页面路径下有一个独立的配置,也就是哪个文件夹你想让它成为页面就添加这个配置就可以了,我们规定它为 page.js 文件,这个文件就承担了当前文件夹页面配置效果,在 about 页面下创建这样一个 js 文件如下

然后将其它你想要当页面的文件夹下面添加 page.js 文件,接下来你要做的就是要找到对应的 page.js 文件,然后通过它生成对应的目录或者路由,当然在找的过程中,需要看你的项目是用什么东西搭建的

如果你是 webpack 的项目,你可以使用 require.context api,来获取指定的文件夹内的特定文件,可以用正则表达式去做对应的匹配,简单的用法如下

代码语言:javascript
复制
const context = require.context("./", true, /\.js$/);
console.log("keys", context.keys());

它会获取你当前目录下所有的以 .js 为后缀的文件,然后调用 keys() 的方法,就能够得到对应文件的路径,假如 ./ 下有 index.js 和 a.js 的文件,上述代码就会返回如下的数据

这是 webpack 的方式,这里我们说一下 vite 怎么获取,对应的 API 是 import.meta.glob,看一下它是干什么的

本质就是可以通过它找到对应目录下的指定的文件,也就是 page.js,我们写一下,看一下最后出来的是什么内容

代码语言:javascript
复制
// src/router.ts
const pages = import.meta.glob('./pages/**/page.js', { eager: true, import: 'default' })
// eager 表示是否直接引入对应的模块
// import default 表示直接获取到 default 的值
console.log('pages', pages)

没加 import: 'default' 的效果

加了 import: 'default' 的效果

属性名是 page.js 的路径,值就是我们配置导出的内容,这样就得到我们想要的数据了

接下来就很简单了,就是要处理这些数据,变成路由的一些配置

代码语言:javascript
复制
const pages = import.meta.glob('./pages/**/page.js', { eager: true, import: 'default' })
const routes: RouteRecordRaw[] = Object.entries(pages).map(([path, config]: [string, any]) => {
  const pathName = path.replace('./pages', '').replace('/page.js', '') || '/'
  const routeName = pathName.split('/').filter(Boolean).join('-') || 'index'
  return {
    path: pathName,
    name: routeName,
    // component 需要单独处理
    // component: () => import(path),
    meta: config
  }
})

一般来说,在 component 这一块,大家都会将 path 中的 page.js 替换成 index.vue 就可以了,但是这样会报错,主要原因是这个 import 会进行抽象语法树的分析,然后根据文件的依赖关系来进行代码的打包,但是由于这里变成了字符串,就导致依赖分析异常,它不知道我们依赖了哪些文件,所以这里这样写是有问题的

所以这里要改,改成 import.meta.glob,然后通过具体的 key value 的形式获取到我们想要的对应的文件内容

完整代码逻辑如下

代码语言:javascript
复制
const pages = import.meta.glob('./pages/**/page.js', { eager: true, import: 'default' })
const pageComponents = import.meta.glob('./pages/**/index.vue', { eager: true, import: 'default' })
const routes: RouteRecordRaw[] = Object.entries(pages).map(([path, config]: [string, any]) => {
  const pathName = path.replace('./pages', '').replace('/page.js', '') || '/'
  const routeName = pathName.split('/').filter(Boolean).join('-') || 'index'
  const componentPath = path.replace('page.js', 'index.vue')
  return {
    path: pathName,
    name: routeName,
    // component 需要单独处理
    component: () => pageComponents[componentPath],
    meta: config
  }
})

这样就能够对文件夹自动生成路由模式,不需要手动添加对应的路由配置,减少了配置的风险,并且对每个页面配置单独抽离,不相互影响,较好的解决了较长的配置文件问题,减少出错

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-09-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FE情报局 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档