基于uni-app开发兼容全端自定义弹出框ua-popup插件,可完美运行在h5、小程序及app端。
uaPopup 一款整合了msg信息框、alert提示框、dialog对话框、actionSheet底部面板框、toast轻提示框、android/ios弹窗等多种弹窗效果。可以自定义弹窗样式及按钮样式和事件、多个弹窗嵌套显示,支持自定义插槽模板内容。
如下图:h5/小程序/app端效果
可覆盖在Nvue原生页面video组件之上
引入组件
uapopup 支持全局main.js引入或页面单独引入使用。
import UAPopup from './components/ua-popup/index.vue'
Vue.component('ua-popup', UAPopup)
自hbuilderx2.5起 支持easycom组件模式。根据使用习惯,也可以改为components/ua-popup/ua-popup.vue方式,系统会自定义识别组件,无需再手动注册引入。
使用组件
ua-popup支持组件写法和函数式写法来调用组件。
- 组件式调用
<!-- msg提示 -->
<ua-popup v-model="showMsg" anim="fadeIn" content="上善若水,水利万物而不争" shadeClose="false" time="3" />
<!-- 询问框 -->
<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},
]"
/>
- 函数式调用
// 函数式多层嵌套
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'},
zIndex: 202120,
btns: [
{
text: 'close', click() {
$ua.close()
}
},
{
text: 'Get一下',
style: 'color:#00aa00;',
click() {
$toast.open({
type: 'toast',
icon: 'loading',
content: '请稍后...',
opacity: .2,
time: 2,
zIndex: 202125,
})
}
}
]
})
}
})
}
编码开发
- 支持如下20+参数自定义配置。
props: {
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
<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="''+uuid" :class="[''+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'+opts.icon]" :style="{'background-image': `url(${toastIcon[opts.icon]})`}"></view> -->
<image v-if="opts.type=='toast'&&opts.icon" class="toast__icons" :class="['toast'+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>
- 核心逻辑处理
<script>
/**
* @Desc uniapp跨端自定义popup组件
* @Time andy by 2021/7/10
* @About Q:282310962 wx:xy190310
*/
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('#' + 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>
基本可通过组件式+函数式组合开发出一些复杂的弹窗应用场景。
okey,基于uniapp开发自定义弹窗组件就分享到这里了。希望对大家有些帮助哈~~✍✍
链接:https://juejin.cn/post/6977298346905960456/
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
8 个评论
要回复文章请先登录或注册
x***@126.com (作者)
9***@qq.com
x***@126.com (作者)
x***@126.com (作者)
baobiao
这是谁的部将
1***@qq.com
x***@126.com (作者)