Skip to content

使用动态 require 解放生产力 #28

@sunorry

Description

@sunorry

使用 Vue TS 开发的时候,大家是不是会这样写。

import currency from './filters/currency'
Vue.filter('currency', currency)

如果有很多 filter,必然要引用多次,一行行"模板"代码会不会看着特别恶心,那么有没有办法自动引用呢?

webpack 支持动态 require,能够完美解决这个问题。

require.context

require.context 可以创建自己的上下文(模块),返回一个(require)函数,这个函数可以接收一个参数:request。

require.context(directory, useSubdirectories = false, regExp = /^\.\//);
  • directory: 要搜索的文件夹目录
  • useSubdirectories:是否还应该搜索它的子目录
  • regExp:匹配文件的正则表达式

示例:

// (创建了)一个包含了 test 文件夹(不包含子目录)下面的、所有文件名以 `.test.js` 结尾的、能被 require 请求到的文件的上下文。
require.context("./test", false, /\.test\.js$/);

// (创建了)一个包含了父级文件夹(包含子目录)下面,所有文件名以 `.stories.js` 结尾的文件的上下文。
require.context("../", true, /\.stories\.js$/);

context module API

require.context 返回一个(require)函数,这个函数可以接收一个参数:reques。

函数包括了 3 个属性:

  • resolve:函数,返回请求被解析后得到的模块 id。
  • keys:函数,返回数组,所有可能被上下文模块处理的请求。
  • id::上下文模块里面所包含的模块 id

这里面最有用的就是 keys了。

如果你想引用一个目录下的所有文件。

function importAll(r) {
  r.keys().forEach(r)
}

importAll(require.context('../views', true, /\.vue$/))

具体代码:

interface ImportAllResult {
  moduleName: string
  camelModuleName: string
  module: any
}

const fileNameRE = /^\.\/([^\s]+)\.ts$/

function importAll(modulesContext: any): ImportAllResult[] {
  return modulesContext.keys().map((modulesPath: string) => {
    const moduleName = (modulesPath.match(fileNameRE) as RegExpMatchArray)[1]
    return {
      moduleName,
      camelModuleName: moduleName.replace(
        /-(\w)/g,
        (_, c) => (c ? c.toUpperCase() : '')
      ),
      module: modulesContext(modulesPath).default // 获取模块默认到处
    }
  })
}

// 在 directives 下新增了指令,也能自动注册
// Registered directives
const dirs = importAll(require.context('@/directives', false, /\.ts$/))
dirs.forEach(dir => {
  Vue.directive(dir.moduleName, dir.module)
})

// Registered filters
const filters = importAll(require.context('@/filters', false, /\.ts$/))
filters.forEach(filter => {
  Vue.filter(filter.moduleName, filter.module)
})
// decorators/
export * from 'vue-property-decorator'
export * from 'vuex-class'

// -----
import Vue from 'vue'
import { Component, Watch, namespace } from '@/decorators'

参考文档:

Dependency Management

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions