在 Vue 中,咱们经过 Vue.component('MyComponentName', { /* ... */ })
的方式来进行全局组件注册,但若是须要全局注册的组件不少,这时代码就会变得比较臃肿,例如:vue
// 注册 5 个全局组件
import ExampleComponent1 from './components/exampleComponent1/index'
import ExampleComponent2 from './components/exampleComponent2/index'
import ExampleComponent3 from './components/exampleComponent3/index'
import ExampleComponent4 from './components/exampleComponent4/index'
import ExampleComponent5 from './components/exampleComponent5/index'
Vue.component('ExampleComponent1', ExampleComponent1)
Vue.component('ExampleComponent2', ExampleComponent2)
Vue.component('ExampleComponent3', ExampleComponent3)
Vue.component('ExampleComponent4', ExampleComponent4)
Vue.component('ExampleComponent5', ExampleComponent5)
复制代码
下面咱们就针对这块痛点,作些优化。git
回看上面的演示代码,最早能想到的优化方式,就是能不能作到批量注册,但查了 Vue 的手册,并无看到组件批量注册的 API。github
没办法,只能改变下思路,既然不能批量注册,那能不能作一层循环,在循环体内依次注册咱们的组件呢?app
答案固然是能够的,来看下个人实现代码:dom
import ExampleComponent1 from './components/exampleComponent1/index'
import ExampleComponent2 from './components/exampleComponent2/index'
import ExampleComponent3 from './components/exampleComponent3/index'
import ExampleComponent4 from './components/exampleComponent4/index'
import ExampleComponent5 from './components/exampleComponent5/index'
const components = {
ExampleComponent1,
ExampleComponent2,
ExampleComponent3,
ExampleComponent4,
ExampleComponent5
}
Object.keys(components).forEach(key => {
Vue.component(key, components[key])
})
复制代码
首先组件仍是要手动引入,引入以后我定义了一个 components
的对象,将引入组件的变量名存放在 components
对象里,最后经过 Object.keys()
方法循环对象并注册组件。学习
这个方法虽然减轻了一部分工做,但实际使用中,依旧仍是比较麻烦,因而我又开始思考可否作到全自动注册。优化
以前在阅读 vue-admin-template 的时候,学习到了一个语法 require.context()
,这是 Webpack 的一个 API ,它能作到遍历文件夹中的指定文件并自动引入。ui
既然能遍历指定文件,还能自动引入,这就已经解决了主要问题了,而我要作无非就是在遍历指定文件的同时,将其注册就能够了。this
下面来看下实现代码:spa
import Vue from 'vue'
const componentsContext = require.context('./components', true, /index.vue$/)
componentsContext.keys().forEach(component => {
// 获取文件中的 default 模块
const componentConfig = componentsContext(component).default
Vue.component(componentConfig.name, componentConfig)
})
复制代码
首先经过 require.context()
获取 ./components 目录下全部文件夹里的 index.vue 文件,而后循环依次读取文件中的 default 模块,并使用组件的 name
作为组件名进行组件注册。
须要注意的是,组件必须设置
name
值,由于注册的组件名就是name
值,因此还要确保不能重名。
export default {
name: 'ExampleComponent1'
}
复制代码
到此为止,咱们已经实现组件的全局自动注册功能了,只需按照规范写好组件,放到 ./components 目录下便可,程序就会自动遍历并注册,无需我再手动操做。
组件有另外一种调用方式,也就是经过 js 调用,例如 ElementUI 里的 Notification 组件,它的调用就是经过 this.$notify()
的方式调用,而 $notify
方法是 ElementUI 挂载到 Vue 原型链上的一个全局方法。
针对这种经过 js 调用的组件,咱们须要在原有组件同目录下增长一个 js 文件,里面的代码以下:
import Vue from 'vue'
const constructor = Vue.extend(require('./main.vue').default)
let instance
const exampleComponent1 = options => {
options = options || {}
instance = new constructor({
data: options
})
instance.vm = instance.$mount()
instance.dom = instance.vm.$el
document.body.appendChild(instance.dom)
return instance.vm
}
export default exampleComponent1
复制代码
这时候,咱们还须要修改一下自动注册的代码。
import Vue from 'vue'
const componentsContext = require.context('./components', true, /index.(vue|js)$/)
componentsContext.keys().forEach(component => {
// 组件配置信息
const componentConfig = componentsContext(component).default
if (/.vue$/.test(component)) {
Vue.component(componentConfig.name, componentConfig)
} else {
Vue.prototype[`$${componentConfig.name}`] = componentConfig
}
})
复制代码
在循环依次读取文件中的 default 模块的时候,判断一下文件是 vue 文件仍是 js 文件,若是是 vue 文件,则进行组件注册,若是是 js 文件,则将组件挂载到 Vue 原型链上。
上面这个 Demo,在实际使用中,就能够经过 this.$exampleComponent1()
的方式调用组件了。
全局组件自动注册的功能也加入到 vue-autumation 中,这是一个基于 Vue CLI 3 制做的 Vue 脚手架,能方便快速进行业务开发,欢迎你们关注。