前言
该文是关于小程序弹框showModal的一个二次封装。用于记录、并与各位掘友交流。
建议阅读时间10-15分钟,欢迎交流。不对之处,请各位掘友不吝赐教与斧正。
封装前后对比
封装优缺点
1、减少每个弹框的调用重复配置项
2、调用方便,支持直接输入字符串作为提示语
3、本文提供的封装版本是:相同提示语只会弹框一次,不同提示语还是会弹框。
4、配置灵活,该弹框基础上,可修改为实现只弹一个弹框等功能
5、封装使用了Promise,这里额外封了一层,使调用更加多样。免得调用时一定要then()或者catch(),不然控制台看着飘红会uncomfortable
6、暂不支持使用editable功能
7、目前该版本做得比较简单。不同提示语多个弹框是同时出来的,导致弹框界面的背景过暗(多个遮罩,微信没有做处理)。在此基础上,可以进一步封装一个外部状态管理器,用于储存多个同时需要提示的弹框,next方法之后执行下一个弹框。这个后续看情况去写吧~
wx.showModal: 显示模态对话框
官方实例代码:
wx.showModal({
title: '提示',
content: '这是一个模态弹窗',
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
封装代码
class ShowModal {
options = {} // 配置项
lastOptions = {} // 上一次的配置项
constructor(options) {
this.init(options)
}
init(options) {
/**
* @param {string || object} options 字符串或者对象。字符串时,提示内容就是options,title默认为“提示”
*/
let optionsInit = {}
if (typeof options === 'string') {
optionsInit.msg = options
} else if (options && typeof options === 'object' && !Array.isArray(options)) {
optionsInit = options
} else {
throw new Error('The params is not a object or string')
}
this.setOptions(optionsInit)
}
setOptions({
msg = '',
title = '提示',
showCancel = true,
confirmColor = '#68C646',
cancelColor = '#333333',
confirmText = '确定',
cancelText = '取消'
} = {}) {
this.options = {
title,
content: msg,
showCancel,
confirmColor,
cancelColor,
confirmText,
cancelText
}
}
show() {
return new Promise((resolve, reject) => {
if (this.lastOptions.content === this.options.content) {
// 屏蔽相同提示语弹框。但callback会直接执行该重复弹框的confirmCallBack
return resolve()
}
this.lastOptions = this.options
uni.showModal({
...this.options,
success: function(res) {
if (res.confirm) {
resolve()
} else if (res.cancel) {
reject()
}
},
fail: () => {
reject()
},
complete: () => {
// 完成后要清除lastOptions,免得点击相同提示框时,第二次不再生效
this.lastOptions = {}
}
})
})
}
}
以下可放在同一文件,也可分开
const createShowModal = (function() {
// 创建单例
let modal
return function(options) {
if (modal) {
modal.init(options)
} else {
modal = new ShowModal(options)
}
return modal
}
})()
class Modal {
// 自定义then, catch, finally,这样就不一定在调用时写then() 或者catch()。否则控制台飘红
confirmCallBack = null
cancelCallBack = null
finallyCallBack = null
init(options) {
this.modal = createShowModal(options)
}
isFunc(fn) {
return typeof fn === 'function'
}
show() {
this.modal.show().then(() => {
typeof this.confirmCallBack === 'function' && this.confirmCallBack()
this.clean()
}).catch(() => {
typeof this.cancelCallBack === 'function' && this.cancelCallBack()
this.clean()
}).finally(() => {
typeof this.finallyCallBack === 'function' && this.finallyCallBack()
this.clean()
})
}
clean() {
// 主动释放内存。当然,小程序也有自己的回收机制
this.confirmCallBack = null
this.cancelCallBack = null
this.finallyCallBac = null
}
then(fn) {
// 设置Modal右边按钮回调
if (!this.isFunc(fn)) {
throw new Error(JSON.stringify(fn) + ' is not a function')
}
this.confirmCallBack = fn
return this
// return entryModal()
}
catch(fn) {
// 设置Modal左边按钮回调
if (!this.isFunc(fn)) {
throw new Error(JSON.stringify(fn) + ' is not a function')
}
this.cancelCallBack = fn
return this
// return entryModal()
}
finally(fn) {
if (!this.isFunc(fn)) {
throw new Error(JSON.stringify(fn) + ' is not a function')
}
this.finallyCallBack = fn
return this
}
}
// const entryModal = (function() {
// // 只设置一个弹框的话可以使用这个,在这个基础上去改。可能还需要配合一个外部的状态管理器
// let modalBox = null
// return function() {
// // 创建唯一并初始化Modal弹框
// if (!modalBox) {
// modalBox = new Modal()
// }
// return modalBox
// }
// })()
const modal = function(options) {
// const modalBox = entryModal()
const modalBox = new Modal()
modalBox.init(options)
modalBox.show()
return modalBox
}
export default modal
使用说明
引入文件,这边用的例子是uniapp
main.js文件
import Modal from '@/utils/Modal'
Vue.prototype.Modal = Modal
具体页面调用示例:
-
- this.Modal('提示内容')
-
- this.Modal({ title: '提示标题', msg: '提示内容' })
-
- this.Modal(options).then(() => {}) // 点击确认回调(右边按钮)
-
- this.Modal(options).catch(() => {}) // 点击取消回调(左边按钮)
-
- this.Modal(options).then(() => {}).catch(() => {}) // 同时有确认和取消的回调
测试下
调用四次,共会弹出3个框:
点击确定时控制台分别输出:
1.1(不会弹框,自动输出)
2(第一个弹框,点击确定输出)
1(第二个弹框,点击确定输出)
0(第三个弹框,点击确定输出)
结语
以上是关于本次showModal的分享,谢谢各位亲的阅读。写得还比较浅,欢迎交流,顺便能给个赞支持一下最好了,毕竟第一次写(^▽^)。