增加摸鱼时间的技巧:vue约定式路由,动态注册全局组件

4,374 阅读4分钟

约定式路由和动态注册组件的好处:

  1. 简化配置:与基于配置的路由不同,Vue约定式路由无需在配置中显式指定每个路由,而是通过一组约定来自动解析路由。这样可以大大简化路由配置,减少开发者需要编写的代码量。
  2. 提高可读性:由于约定式路由基于一组简单的约定,因此代码的可读性更高,开发者可以更容易地理解路由的结构和映射关系。
  3. 易于维护:当应用程序需要更改路由时,开发者只需要遵循一组约定来修改代码即可,而无需对每个路由进行手动配置。
  4. 支持动态路由:Vue约定式路由也支持动态路由,可以根据路由参数生成动态的URL,这对于需要处理多个相似页面的应用程序非常有用。
  5. 更好的扩展性:由于Vue约定式路由与其他Vue生态系统组件和库兼容,因此可以轻松扩展和添加新功能。例如,开发者可以轻松地使用第三方组件库或中间件来增强应用程序的路由功能。

实现:分为webpack和vite两种版本

核心:webpack的require系统

实现约定式路由的核心是webpack提供的require系统,它可以根据特定的上下文来创建一个模块上下文,并在该上下文中搜索指定的模块。具体来说,require.context函数有以下三个参数:

  1. 要搜索的目录
  2. 是否搜索子目录
  3. 搜索模块的正则表达式

动态注册组件(webpack+vue2)

例如,假设我们有以下目录结构:

cssCopy code
.
├── components
│   ├── Button.vue
│   ├── Input.vue
│   └── Modal.vue
└── main.js

我们可以使用require.context函数来搜索components目录下的所有.vue文件:

javascriptCopy code
const files = require.context('./components', false, /.vue$/)

files.keys().forEach(key => {
  const component = files(key).default
  Vue.component(component.name, component)
})

在这个例子中,require.context函数的第一个参数是要搜索的目录,第二个参数是是否搜索子目录(这里设置为false表示只搜索components目录),第三个参数是搜索模块的正则表达式(这里表示搜索以.vue结尾的文件)。调用require.context函数返回一个模块上下文(module context),可以使用该上下文的keys方法来获取符合条件的模块列表。然后我们可以遍历这个列表,加载每个模块并注册Vue组件。

约定式路由的实现(webpack+vue2)

所谓约定式路由是指,我们可以根据一定的约定(例如组件放置的位置和文件名)来自动创建Vue Router的路由配置,从而无需手动编写路由配置,提高开发效率。

假设我们的Vue项目结构如下:

javaCopy code
.
├── src
│   ├── components
│   │   ├── Home.vue
│   │   ├── About.vue
│   │   ├── Product
│   │   │   ├── List.vue
│   │   │   └── Detail.vue
│   │   └── User
│   │       ├── List.vue
│   │       └── Detail.vue
│   └── router.js
└── package.json

我们可以使用require.context函数来自动搜索并加载组件,然后将这些组件自动注册到Vue Router的路由配置中。

在router.js文件中,可以编写如下代码:

javascriptCopy code
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const router = new VueRouter({
  mode: 'history',
  routes: []
})

const files = require.context('./components', true, /.vue$/)

files.keys().forEach(key => {
  const component = files(key).default
  const name = component.name || key.match(//(\w+).vue$/)[1]
  const path = key.replace(/^.//, '').replace(/.\w+$/, '').replace(//index$/, '')

  router.addRoutes([
    {
      path: `/${path}`,
      name,
      component
    }
  ])
})

export default router

在这个例子中,我们首先创建了一个VueRouter实例,并将其路由配置初始化为空数组。然后,使用require.context函数搜索src/components目录下的所有.vue文件,并遍历搜索结果。对于每个搜索结果,我们从中获取组件的默认导出,并根据组件的名称和文件路径来创建路由配置。最后,调用Vue Router的addRoutes方法将路由配置添加到路由配置数组中。

需要注意的是,在路由配置中,我们将文件路径作为路由的路径,并使用组件名称作为路由的名称。如果组件没有设置名称,则使用文件名作为名称。另外,由于组件路径中可能包含子目录,因此需要将路径中的斜杠替换为短横线。最后,我们通过调用Vue Router的addRoutes方法将路由配置添加到路由配置数组中。

vite提供的import.meta.glob

import.meta.glob是Vite中的一个特殊函数,用于动态地加载和解析文件路径,可以方便地实现自动化的模块导入和注册。该函数接受一个字符串参数,表示要匹配的文件路径模式,可以使用通配符和正则表达式来进行模式匹配。

具体来说,import.meta.glob函数返回一个异步迭代器,可以使用for await...of语法遍历匹配到的所有模块,并对每个模块执行指定的操作。在Vite中,import.meta.glob通常用于自动加载和注册Vue组件、路由配置等。

动态注册组件(vite+vue3)

假设我们的Vue 3项目结构如下:

cssCopy code
.
├── src
│   ├── components
│   │   ├── Home.vue
│   │   ├── About.vue
│   │   ├── Product
│   │   │   ├── List.vue
│   │   │   └── Detail.vue
│   │   └── User
│   │       ├── List.vue
│   │       └── Detail.vue
│   └── main.js
└── package.json

我们可以使用import.meta.glob函数来自动搜索并加载组件,并将这些组件自动注册到Vue应用程序中。在main.js文件中,可以编写如下代码:

javascriptCopy code
import { createApp } from 'vue'

const app = createApp()

const modules = import.meta.glob('./components/**/*.vue')

for (const path in modules) {
  const name = path.match(/./(\w+).vue$/)[1]
  const component = await modules[path]()
  app.component(name, component.default || component)
}

app.mount('#app')

在这个例子中,我们首先创建了一个Vue应用程序实例。然后,使用import.meta.glob函数搜索src/components目录及其子目录下的所有.vue文件,并遍历搜索结果。对于每个搜索结果,我们从中获取组件的默认导出,并根据组件的名称来自动注册Vue组件。如果组件没有设置名称,则使用文件名作为名称。最后,我们通过调用Vue应用程序实例的component方法将Vue组件注册到应用程序中。

需要注意的是,在动态注册Vue组件时,我们需要使用异步加载模块的方式,因为模块是动态加载的。另外,在使用import.meta.glob函数搜索模块时,模块路径必须是相对于当前模块的相对路径,并且必须是字符串字面量。

约定式路由(vite+vue3)

根据文件命名规则自动生成路由配置。
以下是一个示例,演示如何使用import.meta.glob和Vue Router实现约定式路由:

javascriptCopy code
// 导入Vue和Vue Router
import { createApp } from 'vue'
import { createRouter, createWebHashHistory } from 'vue-router'

// 创建Vue应用程序实例和Vue Router实例
const app = createApp({})
const router = createRouter({
  history: createWebHashHistory(),
  routes: []
})

// 加载并注册所有Vue组件,并根据文件名自动生成路由配置
const modules = import.meta.glob('./views/**/*.vue')
for (const path in modules) {
  const name = path.match(/./(\w+).vue$/)[1]
  const module = modules[path]
  const component = module.default || module
  router.addRoute({
    path: `/${name}`,
    component: component
  })
}

// 挂载Vue应用程序和Vue Router
app.use(router)
app.mount('#app')

在上面的代码中,我们使用import.meta.glob函数遍历所有以.vue结尾的文件,并根据文件名自动生成路由配置。对于每个文件,我们从文件路径中提取出组件名称,并使用router.addRoute方法添加路由配置。最后,我们使用app.use方法将Vue Router注册到Vue应用程序中。

需要注意的是,为了能够自动注册路由配置,文件命名必须符合一定的规则,例如使用组件名称作为文件名,并将组件名称转换为小写字母和中划线的组合,如home-page.vueabout-us.vue等。这样,我们就可以使用约定式路由来快速构建Vue应用程序,提高开发效率和代码可维护性。