当前位置:   article > 正文

uniapp多端h5+小程序+app弹窗组件|uniApp自定义popup组件_popupdialog slots

popupdialog slots

ua-popup 基于uniapp增强版弹框|对话框|模态框组件。支持超过20+参数、6+弹窗类型及多种弹窗动画,可编译到h5+app+小程序端,可使用组件式+函数式两种调用方式。

在这里插入图片描述
由于uniapp内置的弹窗并不能满足一些复杂的应用场景。只能使用自定义组件来实现效果。虽然官方提供的uni-popup或uview提供的popup组件也能实现一些弹窗效果。但是调用方式非常单一。并不能实现多样化需求。

在这里插入图片描述

引入组件

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

当然也可以改为easycom模式来引入。components/ua-popup/ua-popup.vue
ua-popup可以支持标签方式+函数式调用。

  • 标签式
<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},
    ]"
/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 函数式
<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

对于一些简单提示效果,使用函数式比较方便。一些复杂点的模板可以使用组件式slot插槽调用。

在这里插入图片描述
标题和内容支持富文本插入,并且内容还支持插槽自定义模板内容。

在这里插入图片描述
在这里插入图片描述

<ua-popup v-model="showMulityBtns" anim="fadeInDown" title="<b style='color:#03a9f4;'>Title</b>" :z-index="6666"
			content="<div style='padding:10px 35px;'>Lately did you ever feel the pain In the morning as it soaks it to the bone?</div>"
			:btns="[
				{text: 'later', style: 'color:#aa557f;'},
				{text: 'cancel', style: 'color:#ff5500;'},
				{text: 'ok', style: 'color:#00aa00;', click: handleInfo},
			]"
		/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述
在这里插入图片描述

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
<ua-popup v-model="showComponent" xclose xposition="top" :shadeClose="false" content="自定义模板信息"
			:btns="[
				{text: '确认', style: 'color:#00aa00;', click: hideComponent},
			]"
			@open="handleOpen" @close="handleClose"
		>
			<template slot="content"><div style="color:#aa007f;padding: 0 10px;">实力的来源不是胜利。唯有奋斗才能增强实力。当你历经苦难而不气馁,那便是实力。</div></template>
			<view style="padding: 0 20px 20px;">
				<image src="https://img.yzcdn.cn/vant/apple-2.jpg" style="width:100%;" @click="handleContextPopup" />
			</view>
		</ua-popup>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

uapopup参数配置

## props [参数配置]
v-model				当前组件是否显示
title				标题(支持富文本div标签、自定义插槽内容)
content				内容(支持富文本div标签、自定义插槽内容)
type				弹窗类型(toast | footer | actionsheet | actionsheetPicker | android/ios)
customStyle			自定义弹窗样式
icon				toast图标(loading | success | fail | warn | info)
shade				是否显示遮罩层
shadeClose			是否点击遮罩时关闭弹窗
opacity				遮罩层透明度
round				是否显示圆角
xclose				是否显示关闭图标
xposition			关闭图标位置(left | right | top | bottom)
xcolor				关闭图标颜色
anim				弹窗动画(scaleIn | fadeIn | footer | fadeInUp | fadeInDown)
position			弹出位置(top | right | bottom | left)
follow				长按/右键弹窗(坐标点)
time				弹窗自动关闭秒数(123)
zIndex				弹窗层叠(默认202107)
btns				弹窗按钮(参数:text|style|disabled|click)
------------------------------------------
## slot [插槽]
<template slot="title"></template>
<template slot="content"></template>
------------------------------------------
## emit
open        		打开弹出层时触发(@open="xxx")
close       		关闭弹出层时触发(@close="xxx"------------------------------------------
## event
onOpen      		打开弹窗回调
onClose     		关闭弹窗回调
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143

在nvue原生页面运行效果,兼容性不错。

另外还支持类似微信长按弹窗效果。
在这里插入图片描述
在这里插入图片描述

<!-- 长按弹窗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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

end, 使用uni-app自定义多端弹窗插件就介绍到这里。希望能喜欢~~

https://blog.csdn.net/yanxinyun1990/article/details/118187205

https://blog.csdn.net/yanxinyun1990/article/details/114162969

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/671964
推荐阅读