在 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 腳手架,能方便快速進行業務開發,歡迎你們關注。