做vue项目过程中,很多组件都是可以抽成公共组件,不必每个页面局部引入,用官网的例子表示,可以通过公共组件的方式注册在全局中
Vue.component('component-a', () => import("./component-a"))
Vue.component('component-b', () => import("./component-b"))
Vue.component('component-c', () => import("./component-c"))
想看看vue是怎么实现全局注册,偶然机会发现可以利用webpack的require.context遍历指定的公共组件目录,实现自动化导入模块。仔细看了官网给出的例子,需要全局注册的只需要三样东西,组件名、组件模块、注册;步骤可以分为三步
1.require.context遍历获取所有组件
对于require.context用法,可以在网上或者packweb官网上查看,有详细的说明。require.context会拿到指定目录下所有能匹配上的文件,返回一个函数。
const requireComponent = require.context("./components", true, /\.vue$/);
2.keys(fileName)获取组件名+模块信息
requireComponent.keys()可以拿到组件的 相对路径+组件名 的数组;这时我们只需要把路径和文件后缀剔除,就能拿到组件的名称了,可以使用正则获取到组件名,再用正则将 ‘ - ’ 替换驼峰写法,这里我是直接使用loadash获取的;
其次是获取各个组件模块信息,也就是我们import组件后的对象,let fileConfig = requireComponent(fileName)注意fileName是keys()数组中的值,而不是剔除后的组件名。
3.全局注册
拿到组件名+模块后,就可以进行Vue.component全局注册了
//mian.js
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'//转换首字母为大写
import camelCase from 'lodash/camelCase'//转换字符串为驼峰写法
const requireComponent = require.context(
// 其组件目录的相对路径
'./components',
// 是否查询其子目录
false,
// 匹配基础组件文件名的正则表达式
/Base[A-Z]\w+\.(vue|js)$/
)
requireComponent.keys().forEach(fileName => {
// 获取组件配置
const componentConfig = requireComponent(fileName)
// 获取组件的 PascalCase 命名
const componentName = upperFirst(
camelCase(
// 获取和目录深度无关的文件名
fileName
.split('/')
.pop()
.replace(/\.\w+$/, '')
)
)
// 全局注册组件
Vue.component(
componentName,
// 如果这个组件选项是通过 `export default` 导出的,
// 那么就会优先使用 `.default`,
// 否则回退到使用模块的根。
componentConfig.default || componentConfig
)
})
到这里就完成了导入了,刷新项目后也没出现问题,我的是通过Vue.use()注册插件的方式来,这样可以减少mian.js的代码量,在公共组件conmon目录里建一个index.js,抛出一个install
//conmon/index.js
//全局引入组件
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
const requireComponent = require.context("./", true, /\.vue$/);
const install = (Vue) => {
requireComponent.keys().forEach((fileName) => {
const componentConfig = requireComponent(fileName);
console.log(fileName)
const componentName = upperFirst(
camelCase(
// 获取和目录深度无关的文件名
fileName
.split('/')
.pop()
.replace(/\.\w+$/, '')
)
)
// 全局注册组件
Vue.component(
componentName,
// 如果这个组件选项是通过 `export default` 导出的,
// 那么就会优先使用 `.default`,
// 否则回退到使用模块的根。
componentConfig.default || componentConfig
)
});
};
export default {
install,
};
接着在mian.js注册
//mian.js
import Vue from "vue";
import commonComponents from "components/common/index.js";
Vue.use(commonComponents); //导入全局组件