一、起因
因爲最近在項目用到了大量的Element
的彈窗,每次用到彈窗時都需要用組件的方式去調用,有時候一個頁面需要用到四、五個彈窗,寫在一個頁面組件一是不便於彈窗的維護,二是彈窗組件是渲染在頁面組件的根節點下,而不是掛載在body
下。
所以想想能不能把彈窗組件集中在一個文件管理,通過類似cube-ui
的createAPI
模塊將彈窗組件掛載到body
下。
二、開發
1、彈窗掛載到body
因爲要掛載到body
,所以需要使用JS
去創建彈窗模板,這裏使用Vue的render
函數
const newPopup = new Vue({
data () {
return {
props // 傳入彈窗的props
}
},
render: h => <PopupComponent props={props} /> // h 雖然沒有使用,但必須要寫
})
// 將彈窗組件掛載到body
const popupCom = newPopup.$mount()
document.body.appendChild(popupCom.$el)
2、對外暴露createAPI
方法
對外暴露的createAPI
方法主要功能:接收一個組件列表對象,將每個組件的實例掛載到Vue.prototype.$create[PopupName]
上。
3、完整代碼
// createAPI.js
import Vue from 'vue'
function Popup (component, {props, on}) {
// props:需要傳入彈窗組件的props對象
// on:需要監聽彈窗組件的事件對象
const newPopup = new Vue({
data () {
return {
props
}
},
render: h => <component props={props} on={on} ref='popupDom' /> // Vue render函數的JSX寫法
})
// 將彈窗掛載到body
const popupCom = newPopup.$mount()
document.body.appendChild(popupCom.$el)
// 返回彈窗組件實例
return newPopup.$refs.popupDom
}
function createPopup (component) {
// 創建單例模式
let popupInstance
return (options) => {
return popupInstance = popupInstance || Popup(component, options)
}
}
function upFirstString (string) {
return string.slice(0, 1).toUpperCase() + string.slice(1)
}
function createAPI (Components = {}) {
for (let key in Components) {
let popupName = '$create' + upFirstString(key) // 將彈窗組件名首字母大寫
Vue.prototype[popupName] = createPopup(Components[key])
}
}
// 向外暴露createAPI函數
export default createAPI
三、使用
在Vue
項目的src/components/Popup
目錄下創建createAPI.js
和index.js
文件,createAPI.js
文件就是上面的代碼,index.js
文件用來所有彈窗的引入和管理。
// index.js
import createAPI from './createAPI.js'
// 引入你需要使用的彈窗組件
import Popup1 from './popup1'
import Popup2 from './popup2'
// ...
createAPI({
Popup1,
Popup2
// ...
})
在項目的main.js
文件中將src/components/Popup/index.js
導入
// main.js
import '../src/components/Popup/index' // 導入所有彈窗組件
//...
完整代碼在github上,需要者自行查閱:create-popup