dahong
dahong copied to clipboard
一个高度可定制的vue modal插件
前言
modal 是前端开发中普遍且高频的组件之一,很多UI框架中都会实现modal 来增强实践中的交互,但是都没有达到我想要的,因为开发管理后台类页面时modal 形式多变,而且会相互嵌套,这样的话对可定制性有很大的要求
项目地址
预期目标
- 可以自定义modal,一个vue 组件就是一个modal
- 想要调用modal 直接通过
this.$modal[modal名]()
来调用 -
this.$modal[modal名]()
是个promise,可以根据它的状态来得到modal 上的状态(确定或者取消等) - 可以通过
this.$modal[modal名](params)
来传参复用modal
实现
vue 提供use 函数来让我们安装插件
vue.use(plugin, options)
plugin 可以是object 也可以是function,如果是object 那么需要提供install 方法,如果是function 那么这个function 就是install,use 还提供了options 参数,options 在install 方法中可以获取到
// vuejs-modal.js
var Modal = {
/**
*
*
* @param {Function} Vue
* @param {{name?: string, id?: string, modals: object, style?: object}} options
*/
install: function (Vue, options) {
}
}
install 第一个参数是vue 构造函数,第二个options 就是use 的时候传的options,有了vue 构造函数我们可以做很多事了,我们来是实现下$modal
// vuejs-modal.js
install: function (Vue, options) {
// 定义一个defaultOptions 来初始默认的属性
// 可以通过options 来覆盖掉默认的属性
var defaultOptions = Object.assign({
name: '$modal', //使用this 调用的插件名,默认是$modal
id: 'modal', //html 页面上初始化的div id 名,默认是modal
modals: null, //默认的modals,初始是没有的,需要传参,如果没有会报错
style: {
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 1000
}
// 默认的样式,zIndex 是递增的
}, options)
},
核心:
// 声明一个modals 空间
let modals = Vue.prototype[defaultOptions.name] = {};
// 绑定modal
Object.keys(defaultOptions.modals).forEach(v => {
/**
*
*
* @param {object} options
* @returns
*/
modals[v] = options => {
return new Promise((resolve, reject) => {
try {
new Vue({
render: h => h(defaultOptions.modals[v], {
// 每个modal提供options参数,参数会传递给props
props: options,
style: Object.assign(defaultOptions.style, {
zIndex: this.zIndex
}),
// 默认提供两个事件$on 和$cancel,$on 会resolve,$cancel 会reject
// $on 需要参数$el 来remove 调modal,$cancel 同理
on: {
$ok: function ($el, info) {
$el.remove()
resolve(info)
},
$cancel: function ($el, info) {
$el.remove()
reject(info)
}
}
})
}).$mount('#' + defaultOptions.id)
} catch (error) {
console.error('vuejs-modal', error)
}
})
}
})
问题
- 本来理想情况下是vue 有没有compile 方法提供,这样直接调用compile 后挂载到body 下面,但是看了文档compile 倒是有但是只在独立构建下有用,over,只好使用
new vue()
的方式来变相的compile,但是需要建坑
var div = document.createElement('div');
div.setAttribute('id', 'modal');
document.getElementsByTagName('body')[0].appendChild(div)
- 关闭modal 这个一直有个疑问,是建议使用者手动关闭还是插件来关闭,目前是插件关闭,但是需要把
this.$el传递进来
,后来想了想还是插件关闭,这样的话使用者可以少写一行代码,后续可能会有所调整 - 这个插件不太适用于modal 少且单一的项目,因为我是开发管理后台类页面,modal 页面不是简单的提示信息,会有些交互等,所以和这个插件很契合
- 插件没有很详细的兼容,使用rollup 来打包,并且只引入了promise 和assigin 的Polyfill
- 后续升级看业务中的使用情况
很棒哦
@tflower 谢谢,小东西,没有技术含量的,纯业务驱动
请问这需要vue什么版本
@wangshuai99 2+
顶一个,期待更多分享