Nuxt2如何扩展router实现主题页覆盖与新增自定义页面?
Nuxt.js v2 主题路由自动覆盖&新增实现方案
前置依赖
先安装glob用于快速匹配目录文件:
npm i glob -D
完整配置代码
// nuxt.config.js 顶部先引入依赖 const fs = require('fs') const glob = require('glob') const path = require('path') module.exports = { // 其他配置省略 router: { extendRoutes(routes, resolve) { const theme = process.env.THEME const enableCustom = process.env.THEME_CUSTOMIZE === 'true' // 主主题未开启自定义的场景直接返回 if(theme === "mainTheme" && !enableCustom) return // 1. 定义主题目录优先级:自定义目录 > 当前主题目录 const themeDirs = [] if(enableCustom) themeDirs.push(resolve(__dirname, 'src/themes/customs')) if(theme && theme !== 'mainTheme') themeDirs.push(resolve(__dirname, `src/themes/${theme}`)) // 2. 遍历所有主题目录的vue文件,按优先级合并映射关系 const themeRouteMap = {} themeDirs.forEach(dir => { // 匹配目录下所有.vue文件 const pageFiles = glob.sync('**/*.vue', { cwd: dir }) pageFiles.forEach(file => { // 生成路由标识:去掉.vue后缀,和nuxt默认的chunkName规则一致 const routeKey = file.replace(/\.vue$/, '').replace(/\/index$/, '') // 优先级高的目录会覆盖之前的同key文件 themeRouteMap[routeKey] = path.resolve(dir, file) }) }) // 3. 先覆盖现有路由 routes.forEach(route => { if(themeRouteMap[route.chunkName]) { route.component = themeRouteMap[route.chunkName] // 用完就删,剩下的就是需要新增的路由 delete themeRouteMap[route.chunkName] } }) // 4. 新增主题里独有的路由,按nuxt原生规则生成path和name Object.entries(themeRouteMap).forEach(([routeKey, componentPath]) => { // 转换为nuxt标准路由path let routePath = `/${routeKey}` // 处理动态路由:把路径里的_xxx换成:xxx routePath = routePath.replace(/\/_([^/]+)/g, '/:$1') // 处理index文件:根路径对应/ if(routePath === '/index') routePath = '/' // 生成nuxt标准路由name:路径分段用-连接,动态参数去掉冒号 const routeName = routePath.slice(1).replace(/\//g, '-').replace(/:/g, '') // 推入路由列表 routes.push({ name: routeName, path: routePath, component: componentPath }) }) } } }
疑问对应解答
问题1:动态页面的name、path如何按Nuxt原生规则生成
上面代码里的转换逻辑完全对齐Nuxt2原生路由规则:
- path转换:
- 主题目录下的
about.vue→/about - 主题目录下的
user/_id.vue→/user/:id - 主题目录下的
index.vue→/
- 主题目录下的
- name转换:
/about→ name为about/user/:id→ name为user-id- 嵌套路径
/user/settings→ name为user-settings
问题2:自动遍历主题目录的逻辑说明
- 先定义目录优先级,自定义目录的页面优先级高于普通主题目录,保证自定义可以覆盖所有页面
- 用glob遍历所有主题目录下的vue文件,生成路由标识和文件路径的映射表
- 先匹配现有路由,有对应的主题文件就替换组件,替换完从映射表删掉对应项
- 映射表剩下的就是默认pages目录没有的页面,按规则生成路由后推入路由列表即可
内容的提问来源于stack exchange,提问作者Mojtaba Barari
相关产品推荐
相关产品推荐

