2024-11-13 uniapp自定义全局弹窗并可以通过uni来调用【转载】
新建三个文件:
dialog.js:
export default { /* 链接处理 */ getLink(params) { let url = "/components/dialog/index"; if (params) { let paramStr = ""; for (let name in params) { paramStr += `&${name}=${params[name]}` } if (paramStr) { url += `?${paramStr.substr(1)}` } } return url; }, // 将URL参数分割为对象键值对 getParam(curParam){ // 拼接参数 let param = '' for (let key in curParam) { param += '&' + key + '=' + curParam[key] } // 把参数保存为对像 let obj = {} for (let key in curParam) { obj[key] = curParam[key] } return obj }, /* APP全局弹窗 */ dialog(params = {}, callback) { this.back(); uni.navigateTo({ url: this.getLink(params), success(e) { if (callback != null && typeof callback == "function") { uni.$off("zy_common_dialog"); uni.$on("zy_common_dialog", (type) => { callback && callback(type) }) } } }) }, /*弹出提示弹窗 */ alert(data = {}, callback, close) { let params = { dialogType: "alert", isCloseBtn: '0', isMaskClose: '0', isShow:true, ...data }; this.dialog(params, (type) => { if ("confirm" == type) { callback && callback() } else { close && close() } }) }, /*确认提示框弹窗 */ confirm(data = {}, confirm, cancel, close) { let params = { dialogType: "confirm", isCloseBtn: '0', isMaskClose: '0', isShow:true, ...data }; this.dialog(params, (type) => { if ("confirm" == type) { confirm && confirm() } else if ("cancel" == type) { cancel && cancel() } else if ("close" == type) { close && close() } }) }, /*确认提示框弹窗 */ dialogConfirm(data = {}, confirm, cancel, close) { let params = { dialogType: "dialogOpen", ...data }; this.dialog(params, (type) => { if ("confirm" == type) { confirm && confirm() } else if ("cancel" == type) { cancel && cancel() } else if ("close" == type) { close && close() } }) }, /*消息提示框 */ showMessage(data = {}) { let params = { dialogType: "messageOpen", isMaskClose: '1', ...data }; this.dialog(params) }, /** * 加载框 */ popupLoadingOpen(data = {}) { let params = { dialogType: "popupLoadingOpen", ...data }; this.dialog(params) }, back(isCheckPopupLoading=false){ //保证唯一弹窗 let routes = getCurrentPages(); // 获取当前打开过的页面路由数组 if(routes.length>1){ let curRoute = routes[routes.length - 1].route //获取当前页面路由 if(curRoute=="components/dialog/index"){ if(isCheckPopupLoading){ let curParam = routes[routes.length - 1].options; //获取路由参数 let paramObj=this.getParam(curParam); if(paramObj.dialogType=="popupLoadingOpen") uni.navigateBack(); }else{ uni.navigateBack(); } } } } }
dialogUtils.js:
import dialog from "@/components/dialog/dialog.js" export default { /** * 弹出提示 */ alert(content = "", title = "提示", callback, confirmText = '确定') { // #ifdef APP-PLUS dialog.alert({ content, title, confirmText }, callback) // #endif // #ifndef APP-PLUS uni.showModal({ title, content, confirmText, showCancel: false, confirmColor: "#e03c31", success: callback }) // #endif }, /** * 确认提示框 */ confirm(content = "", confirm, cancel, confirmText = '确定', cancelText = '取消', title = "提示") { // #ifdef APP-PLUS dialog.confirm({ content, title, confirmText, cancelText, }, confirm, cancel) // #endif // #ifndef APP-PLUS uni.showModal({ title, content, cancelText, confirmText, confirmColor: "#e03c31", success: (e) => { if (e.confirm) { confirm && confirm() } else if (e.cancel) { cancel && cancel() } }, fail: (e) => { console.log(e) } }) // #endif }, /** * 确认提示框 * @property {String} content 对话框内容 * @property {function} confirm 对话框内容 */ dialogConfirm(content = "", confirm, cancel, confirmText = '确定', cancelText = '取消', msgType ='info', title = "提示") { // #ifdef APP-PLUS dialog.dialogConfirm({ content, title, confirmText, cancelText, msgType }, confirm, cancel) // #endif // #ifndef APP-PLUS uni.showModal({ title, content, cancelText, confirmText, confirmColor: "#e03c31", success: (e) => { if (e.confirm) { confirm && confirm() } else if (e.cancel) { cancel && cancel() } }, fail: (e) => { console.log(e) } }) // #endif }, showMessage(messageText, msgType="success") { // #ifdef APP-PLUS dialog.showMessage({ msgType, messageText }) // #endif // #ifndef APP-PLUS uni.showToast({ title: content, icon: 'none' }) // #endif }, popupLoadingOpen(popupContent = "加载中...") { // #ifdef APP-PLUS dialog.popupLoadingOpen({ popupContent }) // #endif // #ifndef APP-PLUS uni.showToast({ title: content, icon: 'none' }) // #endif }, popupLoadingClose() { dialog.back(true); } }
index.vue
<template> <view> <!-- 提示信息弹窗 2秒后消失--> <!-- msgType:top、center、bottom、left、right、message、dialog、share --> <view @click="itemClick('mask')" class="mask-content"> <uni-popup ref="message" type="message"> <uni-popup-message :type="info.msgType" :message="info.messageText" :duration="info.duration"></uni-popup-message> </uni-popup> </view> <!-- 加载弹窗 --> <uni-popup ref="popupLoading" :is-mask-click="false"> <view class="popup-content"><text class="cu-load load-cuIcon loading text-white">{{ info.popupContent }}</text> </view> </uni-popup> <!-- 提示信息弹窗 --> <uni-popup ref="alertDialog" type="dialog"> <uni-popup-dialog :type="info.msgType" :cancelText="info.cancelText" :confirmText="info.confirmText" :title="info.title" :content="info.content" @confirm="itemClick('confirm')" @close="itemClick('cancel')" :duration="info.duration"></uni-popup-dialog> </uni-popup> <!-- 自定义提示框 --> <view @click="itemClick('mask')" class="mask-content" v-if="info.isShow"> <view class="dialog-content" @click.stop=""> <view class="head-content " v-if="info.title" :style="info.content ? '' : 'min-height:90rpx;padding:30rpx'"> <text>{{ info.title }}</text> </view> <scroll-view class="main-content" scroll-y v-if="info.content"> <view class="info-content"> <text>{{ info.content }}</text> </view> </scroll-view> <view class="foot-content alert" v-if="'alert' == info.dialogType"> <view class="btn active" @click.stop="itemClick('confirm')"> {{ info.confirmText }} </view> </view> <view class="foot-content confirm" v-if="'confirm' == info.dialogType"> <view class="btn cancel" @click="itemClick('cancel')"> {{ info.cancelText }} </view> <view class="btn active" @click.stop="itemClick('confirm')"> {{ info.confirmText }} </view> </view> </view> </view> </view> </template> <script> export default { name: 'Dialog', data() { return { info: { //消息提示 msgType: 'success', //error、warn、info messageText: '', //确认框 content: "", title: "提示", duration: 2000, cancelText: "取消", confirmText: "确定", dialogType: "", //弹窗类型 0:确认框 1:消息提示 2: 加载框 popupContent: "加载中....", isShow: false, isMaskClose: "1", //1点击遮罩层关闭弹窗 } } }, onLoad(info = {}) { this.info = { ...this.info, ...info }; this.getParams(this.info); }, onUnload() { this.popupLoadingClose(); this.info.dialogType = ""; }, methods: { getParams(options) { switch (options.dialogType) { case "dialogOpen": this.dialogOpen(); break; case "messageOpen": this.messageOpen(); break; case "popupLoadingOpen": this.popupContent = options.popupContent; this.popupLoadingOpen(); break; case "popupLoadingClose": this.popupContent = options.popupContent; this.popupLoadingClose(); break; default: break; } }, /** * 确认框方法 */ dialogOpen() { this.$nextTick(() => { this.$refs.alertDialog.open(); }) }, /** * 消息提示框方法 */ messageOpen() { if (this.info.dialogType == "messageOpen") { this.$nextTick(() => { if (this.$refs.message) { this.$refs.message.open(); this.setTimeOut = setTimeout(() => { uni.navigateBack() }, this.info.duration) } }); } }, /** * 加载框方法 */ popupLoadingOpen() { this.$nextTick(() => { this.$refs.popupLoading.open('center'); }); }, /** * 废弃,页面路由使用不上 * 直接使用uni.navigateBack() */ popupLoadingClose() { this.$refs.popupLoading.close(); }, itemClick(type) { if (type == "mask" && this.info.isMaskClose != '1') { return; } //解决消息提示的自动消失返回的bug if (this.setTimeOut) clearTimeout(this.setTimeOut); uni.navigateBack(); uni.$emit("zy_common_dialog", type); } } }; </script> <style lang="scss"> $btncolor: #0081ff; page { background: transparent; } .mask-content { position: fixed; left: 0; top: 0; right: 0; bottom: 0; display: flex; justify-content: center; align-items: center; background-color: rgba(0, 0, 0, 0.4); .dialog-content { background-color: #FFFFFF; width: 580rpx; border-radius: 10rpx; .head-content { display: flex; align-items: center; justify-content: center; color: #343434; font-weight: bold; font-size: 32rpx; padding: 20rpx 30rpx; } .main-content { max-height: 330rpx; .info-content { min-height: 80rpx; padding: 10rpx 30rpx; color: #636463; font-size: 30rpx; display: flex; justify-content: center; align-items: center; } } .foot-content { display: flex; justify-content: center; align-items: center; height: 110rpx; .btn { font-size: 28rpx; border-radius: 66rpx; height: 66rpx; display: flex; justify-content: center; align-items: center; } &.alert { .btn { background-color: $btncolor; color: #FFFFFF; font-size: 28rpx; border-radius: 60rpx; height: 66rpx; width: 300rpx; padding: 0 40rpx; display: flex; justify-content: center; align-items: center; } } &.confirm { justify-content: space-around; .btn { min-width: 230rpx; &.active { background-color: $btncolor; color: #FFFFFF; } &.cancel { border: 1rpx solid $btncolor; color: $btncolor; border-radius: 66rpx; } } } } } } </style>
在pages.json中插入这个组件路径:
{ "path": "components/dialog/index", "style": { "navigationStyle": "custom", "app-plus": { "animationType": "fade-in", "background": "transparent", "popGesture": "none" } } }
最后在app.vue中调用:
export default { onLaunch() { uni['dialog'] = dialog; }, mounted() { uni.dialog.alert("消息文本","提示",()=>{ uni.showToast({ title: '好的', icon:"none" }); },"好的"); }
效果:
注:本文转载至https://gitcode.csdn.net/65e83d4c1a836825ed78b175.html
最后:我修改了一下dialogUtils.js的语法,把commonJs语法改成了ESM语法。