news 2026/4/16 15:33:44

uniapp定义一个简单的全局弹窗组件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
uniapp定义一个简单的全局弹窗组件

兼容H5、微信小程序、安卓APP

(1)封装成组件

dialog.js

export default { /* 链接处理 */ getLink(params){ let url = "/components/dialog/dialog"; if(params){ let paramStr = ""; for(let name in params){ paramStr+=`&${name}=${params[name]}` } if(paramStr){ url +=`?${paramStr.substr(1)}` } } return url; }, /* APP全局弹窗 */ dialog(params={},callback){ const store = getApp().globalData.store store.commit('setAppDialogShow', true) uni.navigateTo({ url:this.getLink(params), success(e) { uni.$off("wujw_common_dialog"); uni.$on("wujw_common_dialog",(type)=>{ callback&&callback(type) }) } }) }, /*弹出提示弹窗 */ alert(data={},callback,close){ let params = {type:"alert",isCloseBtn:'0',isMaskClose:'0',...data}; this.dialog(params,(type)=>{ if("confirm"==type){ callback&&callback() }else { close&&close() } }) }, /*确认提示框弹窗 */ confirm(data={},confirm,cancel,close){ let params = {type:"confirm",isCloseBtn:'0',isMaskClose:'0',...data}; this.dialog(params,(type)=>{ if("confirm"==type){ confirm&&confirm() }else if("cancel"==type){ cancel&&cancel() }else if("close"==type){ close&&close() } }) }, }

dialog.vue

<template> <view @click="itemClick('mask')" class="mask-content"> <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.type"> <view class="btn active" @click.stop="itemClick('confirm')"> {{info.confirmText}} </view> </view> <view class="foot-content confirm" v-if="'confirm'==info.type"> <view class="btn cancel" @click="itemClick('cancel')"> {{info.cancelText}} </view> <view class="btn active" @click.stop="itemClick('confirm')"> {{info.confirmText}} </view> </view> </view> </view> </template> <script> export default { data() { return { info: { type: "alert", //alert:单按钮,confirm:双按钮 title: "", // content: "", cancelText: "取消", confirmText: "确定", isMaskClose: "1", //1点击遮罩层关闭弹窗 } } }, onLoad(info = {}) { this.info = { ...this.info, ...info }; }, methods: { itemClick(type) { if (type == "mask" && this.info.isMaskClose != '1') { return; } uni.navigateBack() uni.$emit("wujw_common_dialog", type); // #ifdef APP const store = getApp().globalData.store store.commit('setAppDialogShow', false) // #endif } } } </script> <style lang="scss"> $btncolor: #ff6a00; 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; &:active{ background-color: #eeeeee; } } &.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>

dialogUtil.js

import dialog from "@/components/dialog/dialog.js" export default { /** * 弹出提示 */ alert({ title = "", content = "", confirmText = '确定', callback, }) { // #ifdef APP-PLUS dialog.alert({ content, title, confirmText }, callback) // #endif // #ifndef APP-PLUS uni.showModal({ title, content, confirmText, showCancel: false, confirmColor: '#ff6a00', success: callback }) // #endif }, /** * 确认提示框 */ confirm({ title = "提示", content = "", confirmText = '确定', cancelText = '取消', confirm, cancel }) { // #ifdef APP-PLUS dialog.confirm({ content, title, confirmText, cancelText, }, confirm, cancel) // #endif // #ifndef APP-PLUS uni.showModal({ title, content, cancelText, confirmText, confirmColor: '#ff6a00', success: (e) => { if (e.confirm) { confirm && confirm() } else if (e.cancel) { cancel && cancel() } }, fail: (e) => { console.log(e) } }) // #endif }, }

(2)配置page.json

在pages的最底部设置(APP端才需要)

// #ifdef APP-PLUS , { "path": "components/dialog/dialog", "style": { "navigationStyle": "custom", // #ifdef APP-PLUS "backgroundColor": "transparent", "backgroundColorTop": "transparent", "backgroundColorBottom": "transparent", // #endif "app-plus": { "animationType": "fade-in", "background": "transparent", "popGesture": "none" } } } // #endif

(3)配置App.vue

<script> import dialog from "@/components/dialog/dialogUtil.js" export default { async onLaunch() { uni['dialog'] = dialog; }, } </script>

(4)调用

注意:不需要再次引入组件,可直接在script调用

// 显示双按钮 uni.dialog.confirm({ title: "温馨提示", content: "您当前的网络不稳定,请检查网络状态", confirmText: "好的", confirm: () => { console.log("已点击确认"); }, }); // 显示单按钮 uni.dialog.alert({ content: "您当前的网络不稳定,请检查网络状态", confirm: () => { console.log("已点击确认"); }, });

(5)注意App端的一个问题

在uniapp(App端)中实现自定义弹框,可以通过创建一个透明页面来实现。点击进入当前页面时,页面背景会变透明,用户可以根据自己的需求进行自定义,最终效果类似于弹框。

遇到问题:当打开弹窗(进入弹窗页面)就会触发当前页面的onHide函数,关闭弹窗(跳出弹窗页面)就会触发上一页的onShow函数。有时候我们在onShow、onHide函数会定义自己的逻辑处理,比如在onShow函数发请求、在onHide销毁定时器,那么当打开关闭弹窗都会触发一遍。当打开关闭弹窗避免不触发自己定义的逻辑处理,这问题怎么解决呢?

解决逻辑:

1、我们可以在vuex定义一个变量,默认为false,当打开弹窗(进入弹窗页面)之前把该变量改成true,关闭弹窗(跳出弹窗页面)之后把该变量改成false。(或者直接使用uni.getStorageSync本地存储和uni.removeStorageSync删除缓存也可以。)

2、在调用弹窗的页面的onShow、onHide函数获取到该变量,判断变量如果为true,直接结束函数。
vuex的store 定义一个弹窗状态和改变状态的方法

state: { appDialogShow: false, }, mutations: { setAppDialogShow(state, show) { state.appDialogShow = show; },

App进入、进出弹窗页面改变弹窗状态


App端在页面调用弹窗组件,就会触发onShow、onHide函数,需要做判断禁止再次触发

H5效果图

微信小程序效果图

App效果图

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 19:36:11

Git Restore 命令教程

Git Restore 命令教程 简介 git restore 是 Git 2.23 版本引入的一个相对新的命令&#xff0c;用于恢复工作目录或暂存区中的文件。它提供了一个直观的方式来撤销更改&#xff0c;取代了之前使用 git checkout 的一些用法。 这个命令的推出使得 Git 的命令更加清晰和易用&am…

作者头像 李华
网站建设 2026/4/16 12:28:44

JavaScript WebAPI 核心操作指南

JavaScript(WebAPI) WebAPI 背景知识 什么是 WebAPI 前面学习的 JS 分成三个大的部分&#xff1a; ECMAScript&#xff1a;基础语法部分DOM API&#xff1a;操作页面结构BOM API&#xff1a;操作浏览器 WebAPI 就包含了 DOM BOM。 这个是 W3C 组织规定的&#xff08;和制…

作者头像 李华
网站建设 2026/4/16 14:04:48

FastGPT完全部署指南:从零搭建大语言模型知识平台

本文详细介绍FastGPT项目的部署与使用。作为基于大语言模型的知识型平台&#xff0c;它支持数据处理、RAG检索等功能。文章从安装Git到配置Docker环境&#xff0c;解决了config.json路径问题&#xff0c;演示了LLM和embedding模型配置&#xff0c;展示了其在PDF处理、图片标注和…

作者头像 李华
网站建设 2026/4/7 3:21:39

AI大模型学习宝典:从技术入门到商业应用,全方位掌握_大模型产品经理课程(非常详细)大模型入门到精通

AI大模型行业处于萌芽期但增速迅猛&#xff0c;AIGC人才需求激增&#xff0c;尤其是AI产品经理。文章介绍AI产品经理的定义、职责、职业优势及四阶段学习路径&#xff1a;初阶应用、高阶应用、模型训练和商业闭环。作者提供完整学习资源&#xff0c;包括思维导图、书籍、视频教…

作者头像 李华
网站建设 2026/4/16 14:04:11

人形机器人秀出武术动作,背后藏着算力密码

刷到宇树 H2 的训练视频了吗&#xff1f;180 厘米高、70 公斤重的 “钢铁巨人” 一记飞踢精准命中沙袋&#xff0c;紧接着侧空翻落地稳如磐石&#xff0c;整套动作丝滑得不像机器执行。但你知道吗&#xff1f;这看似简单的动作背后&#xff0c;藏着 31 个关节的冗余控制难题与 …

作者头像 李华