uaPopup 基於uniapp開發的相容多端h5+小程式+app端
自定義彈框元件。
快速引入
在main.js中全域性引入。
import UAPopup from './components/ua-popup/index.vue'
Vue.component('ua-popup', UAPopup)
也可以使用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="showInfo" anim="scaleIn"
content="陽光下人走不出自己的影子,黑暗中人看不見自己的影子。只要還有明天,今天就永遠是起跑線。"
:btns="[
{text: '知道了', style: 'color:#999;', click: hideInfo},
]"
/>
- 函式式
// 函式式巢狀呼叫
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,
})
}
}
]
})
}
})
},
handleBtnClick() {
this.$refs.uapopup.open({
content: '正在操作中,請稍後...',
shadeClose: false,
anim: 'footer',
customStyle: {'background-color': 'rgba(0, 170, 0, 0.6)', 'color': '#fff', 'border-radius': '6px'},
opacity: .1,
time: 2,
onClose: () => {
this.$refs.uatoast.open({
type: 'toast', icon: 'success', content: '操作成功', time: 2,
})
}
});
},
實現過程
- 支援20+引數配置
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 彈窗自動關閉秒數(1、2、3) zIndex 彈窗層疊(預設202107) btns 彈窗按鈕(引數:text|style|disabled|click) open 開啟彈出層時觸發(@open="xxx") close 關閉彈出層時觸發(@close="xxx") onOpen 開啟彈窗回撥 onClose 關閉彈窗回撥
<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>
<script>
/**
* @Desc uniapp全端自定義彈框元件
* @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('#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>
好了,以上就是uniapp開發自定義彈窗的分享。希望對大家有些幫助!
Electron11模仿QQ+微信桌面端聊天|vue3.x+antdv+electron跨端聊天應用
electron13+vue3混合式桌面exe應用框架ElectronMacUI
本作品採用《CC 協議》,轉載必須註明作者和本文連結