uniapp兼容多端自定义模态弹框组件UAPopup

ua-popup 一款轻量级的uniapp自定义弹窗组件。汇集了android、ios和微信弹窗效果(msg消息、alert提示框、dialog对话框、actionsheet底部动作框、toast轻提示、长按定位菜单)等功能。

如下图:H5+App端+小程序效果,亲测多端运行一致。

◆ 引入使用

 ▍在main.js中引入uapopup弹框组件

// 引入自定义弹框组件
import uaPopup from './components/ua-popup/index.vue'
Vue.component('ua-popup', uaPopup)

说明:自HBuilderX 2.5.5起支持easycom组件模式。只要组件在components目录,并且符合 components/ua-popup/ua-popup.vue 结构。则无需引入组件,直接在页面使用即可。

UApopup支持标签组件式+函数式两种调用方式。

  • 标签式
<!-- msg提示(自定义背景) -->
<ua-popup
v-model="showMsgBg"
anim="footer"
content="hello uniapp"
shade="false"
time="2"
:custom-style="{'backgroundColor': 'rgba(0,0,0,.6)', 'color': '#fff'}"
/> <!-- 询问框 -->
<ua-popup v-model="showConfirm" shadeClose="false" title="标题" xclose z-index="2001"
content="<div style='color:#ff557f;padding:20px 40px;'>一切都将一去杳然,任何人都无法将其捕获。</div>"
:btns="[
{text: '取消', click: hideConfirm},
{text: '确定', style: 'color:#00aa00;', click: handleInfo},
]"
/>
  • 函数式
<script>
export default {
methods: {
// 函数式嵌套调用
handleInfo() {
let $ua = this.$refs.uapopup
let $toast = this.$refs.uatoast
$ua.open({
content: '人生漫漫,且行且珍惜',
customStyle: {'background-color': 'rgba(170, 0, 127, 0.6)', 'color': '#fff'},
time: 3,
onClose() {
$ua.open({
type: 'android',
content: '<div style="color:#aa007f">预测未来的最好办法是自己亲手创造未来</div>',
customStyle: {'width': '200px'},
btns: [
{
text: 'close', click() {
$ua.close()
}
},
{
text: 'Get一下',
style: 'color:#00aa00;',
click() {
$toast.open({
type: 'toast',
icon: 'loading',
content: '请稍后...',
opacity: .2,
time: 2,
})
}
}
]
})
}
})
},
}
}
</script>

说明:一些简单的提示使用函数式调用足以,如果复杂的模板展示,则推荐使用组件式调用(支持slot插槽)

  • 简单消息提示

<ua-popup v-model="showMsg" anim="fadeIn" content="上善若水,水利万物而不争" shadeClose="false" time="3" />
  • 底部弹框效果

<!-- 底部对话框 -->
<ua-popup v-model="showFooter" anim="footer" type="footer" :shadeClose="false"
content="真正觉悟的一刻,是放下追寻外在世界的财富,而开始追寻内心世界的真正财富。"
:btns="[
{text: 'Get到了', style: 'color:#00e0a1;', click: handleInfo},
{text: '收藏', style: 'color:#ee0a24;'},
{text: '取消', style: 'color:#a9a9a9;', click: hideFooter},
]"
/> <!-- ActionSheet底部弹出式菜单 -->
<ua-popup v-model="showActionPicker" anim="footer" type="actionsheetPicker" round title="标题"
:btns="[
{text: '取消'},
{text: '确定', style: 'color:#00aa00;', click: handleInfo},
]"
>
<!-- 自定义内容 -->
<ul class="list" style="padding:50px;">
<li>只要不失去方向,就不会失去自我</li>
<li>别问别人为什么,多问自己凭什么</li>
<li>不要等待机会,而要创造机会</li>
</ul>
</ua-popup>
  • 轻提示loading

<ua-popup v-model="showToast" type="toast" icon="loading" time="2" content="加载中..." />
<!-- <ua-popup v-model="showToast" type="toast" icon="success" shade="false" time="2" content="成功提示" /> -->
<!-- <ua-popup v-model="showToast" type="toast" icon="fail" shade="false" time="2" content="失败提示" /> -->
<!-- <ua-popup v-model="showToast" type="toast" icon="warn" shade="false" time="2" content="警告提示" /> -->
<!-- <ua-popup v-model="showToast" type="toast" icon="info" shade="false" time="2" content="普通提示" /> -->
  • 长按菜单效果

<!-- 长按弹窗1 -->
<ua-popup v-model="showContextMenu1" type="contextmenu" :follow="follow1" opacity=".35"
:btns="[
{text: '置顶聊天', click: handleContextPopup},
{text: '标记为未读', style: 'color:#00aa00;'},
{text: '少一点预设的期盼,那份对人的关怀会更自在', style: 'color:#ff007f;'},
{text: '心有多大,舞台就有多大', style: 'color:#09f;'},
{text: '关闭', style: 'color:#aaaa7f;', click: hideContextMenu1},
]"
>
</ua-popup> <!-- 长按弹窗2 -->
<ua-popup v-model="showContextMenu2" type="contextmenu" :follow="follow2" opacity="0"
:btns="[
{text: '置顶联系人', click: handleContextPopup},
{text: '设置备注信息'},
{text: '星标好友'},
{text: '删除', click: hideContextMenu1},
]"
>
</ua-popup>

注意:需要传入follow坐标点参数。

// 长按菜单操作
handleContextMenu1(e) {
this.showContextMenu1 = true;
this.follow1 = [e.touches[0].clientX, e.touches[0].clientY]
},

very nice! 是不是觉得这款插件还不错,也是倒腾了几个通宵搞出来的。尤其调试nvue页面,简直让人有点抓狂~~

◆ UApopup编码实现

  • 支持20+参数配置
props: {
// 接收父组件中v-model的值
value: { type: Boolean, default: false },
title: String,
content: String,
type: String,
customStyle: { type: Object, default: null },
icon: String,
shade: { type: [Boolean, String], default: true },
shadeClose: { type: [Boolean, String], default: true },
opacity: { type: [Number, String], default: '' },
round: Boolean,
xclose: Boolean,
xposition: { type: String, default: 'right' },
xcolor: { type: String, default: '#333' },
anim: { type: String, default: 'scaleIn' },
position: String,
follow: { type: Array, default: null },
time: { type: [Number, String], default: 0 },
zIndex: { type: [Number, String], default: '202107' },
btns: {
type: Array, default: null
},
// 打开弹框回调
onOpen: { type: Function, default: null },
// 关闭弹框回调
onClose: { type: Function, default: null },
},
  • 弹框模板
<template>
<!-- #ifdef APP-NVUE -->
<view v-if="opts.visible" class="ua__popup" :class="{'ua__popup-closed': closeAnim}">
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<view v-show="opts.visible" class="ua__popup" :class="{'ua__popup-closed': closeAnim}">
<!-- #endif -->
<!-- 遮罩层 -->
<view v-if="opts.shade && opts.shade!='false'" class="uapopup__overlay" @touchstart="handleShadeClick" :style="{'opacity': opts.opacity >= 0 ? opts.opacity : '', 'z-index': oIndex-1}"></view>
<!-- 窗口层 -->
<view class="uapopup__wrap" :style="{'z-index': oIndex}">
<view class="uapopup__child" :id="'uapopup-'+uuid" :class="['anim-'+opts.anim, opts.type&&'popui__'+opts.type, opts.round&&'round', opts.position]" :style="[opts.follow&&positionStyle, opts.customStyle]">
<!-- //标题 -->
<view v-if="opts.title || $slots.title" class="uapopup__title">
<template v-if="$slots.title"><slot name="title" /></template>
<rich-text v-else :nodes="opts.title"></rich-text>
</view> <!-- //toast -->
<!-- <view v-if="opts.type=='toast'&&opts.icon" class="toast__icons" :class="['toast__icons-'+opts.icon]" :style="{'background-image': `url(${toastIcon[opts.icon]})`}"></view> -->
<image v-if="opts.type=='toast'&&opts.icon" class="toast__icons" :class="['toast__icons-'+opts.icon]" :src="toastIcon[opts.icon]" mode="widthFix"></image>
<!-- //内容 -->
<view v-if="opts.content || $slots.content" class="uapopup__content">
<template v-if="$slots.content"><slot name="content" /></template>
<rich-text v-else :nodes="opts.content"></rich-text>
</view>
<slot /> <!-- //按钮组 -->
<view v-if="opts.btns" class="uapopup__actions">
<rich-text v-for="(btn,index) in opts.btns" :key="index" class="btn" :class="{'disabled': btn.disabled}" :style="btn.style" @click="handleBtnClick($event, index)" :nodes="btn.text"></rich-text>
</view> <!-- //关闭按钮 -->
<view v-if="opts.xclose" class="uapopup__xclose" :class="opts.xposition" :style="{'color': opts.xcolor}" @click="close"></view>
</view>
</view>
</view>
</template> /**
* @Desc uniapp全端自定义弹框组件
* @Time andy by 2021/7/10
* @About Q:282310962 wx:xy190310
*/
<script>
let index = 0
export default {
...
data() {
return {
// 混入props参数,处理函数式调用
opts: {
visible: false,
},
toastIcon: {
...
},
closeAnim: false,
oIndex: 202107,
timer: null,
// 长按定位初始化(避免弹框跳动闪烁)
positionStyle: { position: 'absolute', left: '-999px', top: '-999px' },
}
},
watch: {
value(val) {
const type = val ? 'open' : 'close'
this[type]()
}
},
computed: {
uuid() {
return Math.floor(Math.random() * 10000)
},
},
methods: {
// 打开弹框
open(options) {
if(this.opts.visible) return
this.opts = Object.assign({}, this.$props, options)
this.opts.visible = true // nvue 的各组件在安卓端默认是透明的,如果不设置background-color,可能会导致出现重影的问题
// #ifdef APP-NVUE
if(!this.opts.customStyle['background'] && !this.opts.customStyle['background-color']) {
this.opts.customStyle['background'] = '#fff'
}
// #endif let _index = ++index
this.oIndex = _index + parseInt(this.opts.zIndex) this.$emit('open')
typeof this.opts.onOpen === 'function' && this.opts.onOpen() // 长按处理
if(this.opts.follow) {
...
} ...
},
// 关闭弹框
close() {
if(!this.opts.visible) return this.closeAnim = true
setTimeout(() => {
this.opts.visible = false
this.closeAnim = false this.$emit('input', false)
this.$emit('close')
typeof this.opts.onClose === 'function' && this.opts.onClose() this.timer && clearTimeout(this.timer)
delete this.timer
}, 200)
}, ... // 获取dom宽高
getDom(id) {
return new Promise((resolve, inject) => {
uni.createSelectorQuery().in(this).select('#uapopup-' + id).fields({
size: true,
}, data => {
resolve(data)
}).exec()
})
}, // 自适应坐标点
getPos(x, y, ow, oh, winW, winH) {
let l = (x + ow) > winW ? x - ow : x;
let t = (y + oh) > winH ? y - oh : y;
return [l, t];
},
}
}
</script>

最后是运行在video页面效果图,完美的兼容性。

好了,基于uni-app开发多端自定义弹窗组件就分享到这里。希望对大家有点帮助哈!✍

最后附上vue3+electron实例项目

electron+vue3跨端仿QQ聊天:https://www.cnblogs.com/xiaoyan2017/p/14454624.html

electron+vite2后台管理系统:https://www.cnblogs.com/xiaoyan2017/p/14776441.html

基于uni-app全端弹框组件uaPopup「兼容h5+小程序+app端|nvue」的更多相关文章

  1. 基于uniapp自定义Navbar+Tabbar组件「兼容H5+小程序+App端Nvue」

    uni-app跨端自定义navbar+tabbar组件|沉浸式导航条|仿咸鱼凸起标签栏 在跨端项目开发中,uniapp是个不错的框架.采用vue.js和小程序语法结构,使得入门开发更容易.拥有非常丰富 ...

  2. vue3系列:vue3.0自定义弹框组件V3Popup|vue3.x手机端弹框组件

    基于Vue3.0开发的轻量级手机端弹框组件V3Popup. 之前有分享一个vue2.x移动端弹框组件,今天给大家带来的是Vue3实现自定义弹框组件. V3Popup 基于vue3.x实现的移动端弹出框 ...

  3. svelte组件:Svelte自定义弹窗Popup组件|svelte移动端弹框组件

    基于Svelte3.x自定义多功能svPopup弹出框组件(组件式+函数式) 前几天有分享一个svelte自定义tabbar+navbar组件,今天继续带来svelte自定义弹窗组件. svPopup ...

  4. 自己写的基于bootstrap风格的弹框插件

    自己写的一款基于bootstrap风格的弹框插件,暂时只有确认框.提示框.后续功能扩展.bug修改再更新. ;(function($){ //默认参数 var PARAMS; var DEFAULTP ...

  5. 移动端(H5)弹框组件--简单--实用--不依赖jQuery

    俗话说的好,框架是服务与大家的,包含的功能比较多,代码多.在现在追求速度的年代.应该根据自己的需求去封装自己所需要的组件. 下边就给大家介绍一下自己封装的一个小弹框组件,不依赖与jQuery,代码少, ...

  6. VUE2.0增删改查附编辑添加model(弹框)组件共用

    Vue实战篇(增删改查附编辑添加model(弹框)组件共用) 前言 最近一直在学习Vue,发现一份crud不错的源码 预览链接 https://taylorchen709.github.io/vue- ...

  7. 解决关闭app权限弹框后无法识别页面对象问题

    在使用appium进行安卓端app的自动化测试,我碰到这样下面这几个问题: 1.每次启动我的待测app时总会提示app权限 2.关闭完权限后,无法识别页面对象 第一个问题的解决,我更换不同的真机进行测 ...

  8. uniapp自定义顶部搜索框兼容微信小程序

    zhuanzai:  uniapp自定义顶部搜索框兼容微信小程序 自定义组件 navbarvue (胶囊底部高度 - 状态栏的高度) + (胶囊顶部高度 - 状态栏内的高度) = 导航栏的高度 < ...

  9. 微信小程序APP(商超营销类)经验总结

    项目介绍 这是一款主打门店营销的小程序.包括首页.门店.营销.个人设置.登录.数据统计展示.营销设置等. 本来要独立完成整个项目,包括前后端一套的,有些意外因素,项目临时收尾(说明:只完成了前端的部分 ...

随机推荐

  1. Linux讲解之定时任务

    https://www.php.cn/linux-369884.html Linux讲解之定时任务 原创2018-05-14 10:11:3101319 本文目录: 12.1 配置定时任务 1 ...

  2. 搭建 Linux 集群环境

    什么是集群 集群是一组通过网络互联的计算机,集群里的每一台计算机称作一个节点. 搭建集群环境规划 集群主机节点数:4 台安装 CentOS7 的虚拟机 主机名(Hostname) IP 地址 node ...

  3. CGI开发-(转自 jemofh159)

    随着Internet技术的兴起,在嵌入式设备的管理与交互中,基于Web方式的应用成为目前的主流,这种程序结构也就是大家非常熟悉的B/S结构,即在嵌入式设备上运行一个支持脚本或CGI功能的Web服务器, ...

  4. workbench msvcr120.dll 文件缺失问题

    开始以为是dll文件缺失,后来下载了好几个版本的替换到system32文件夹下.依然不起作用. 后来看到解决办法了,原文在此:http://forums.mysql.com/read.php?169, ...

  5. Java核心技术卷阅读随笔--第3章【Java 的基本程序设计结构】

    Java 的基本程序设计结构 现在, 假定已经成功地安装了 JDK,并且能够运行第 2 章中给出的示例程序.我们从现在开始将介绍 Java 应用程序设计.本章主要介绍程序设计的基本概念(如数据类型.分 ...

  6. java并发编程工具类JUC第四篇:LinkedBlockingQueue链表队列

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue. LinkedBlockingQueue 队列是Blo ...

  7. Linux(CentOS7)下rpm安装MySQL8.0.16

    记录一下自己在 CentOS7 下 rpm 安装 MySQL8.0.16 的过程. 一.准备工作 1. 下载MySQL所需要的安装包 从 MySQL官网 下载,上传至 CentOS 系统 /usr/l ...

  8. GO语言基础---值传递与引用传递

    package main import ( "fmt" ) /* 值传递 函数的[形式参数]是对[实际参数]的值拷贝 所有对地址中内容的修改都与外界的实际参数无关 所有基本数据类型 ...

  9. TensorFlow反向传播算法实现

    TensorFlow反向传播算法实现 反向传播(BPN)算法是神经网络中研究最多.使用最多的算法之一,用于将输出层中的误差传播到隐藏层的神经元,然后用于更新权重. 学习 BPN 算法可以分成以下两个过 ...

  10. 功率半导体碳化硅(SiC)技术

    功率半导体碳化硅(SiC)技术 Silicon Carbide Adoption Enters Next Phase 碳化硅(SiC)技术的需求继续增长,这种技术可以最大限度地提高当今电力系统的效率, ...