一、起因
因为最近在项目用到了大量的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