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语法。

浙公网安备 33010602011771号