Vue 全局组件自动注册

在 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 脚手架,能方便快速进行业务开发,欢迎你们关注。

相关文章
相关标签/搜索