之前有開發過一個vue2手機端彈層,今天分享的是Vue3版彈框元件。
V3Popup 基於vue3.0
開發的簡易手機版彈框元件。支援6+彈框型別、7+動畫效果、20+自定義引數
配置。
在功能及效果上和之前vue2基本保持一致。
通過如下方法即可快速引入v3popup彈框元件。
import { createApp } from 'vue'
import App from './App.vue'
// 引入彈窗元件v3popup
import V3Popup from './components/v3popup'
createApp(App).use(V3Popup).mount('#app')
支援如下20+自定義引數任意搭配,實現各種彈窗效果。
|props引數|
v-model 是否顯示彈框
title 標題
content 內容(支援String、帶標籤內容、自定義插槽內容)***如果content內容比較複雜,推薦使用標籤式寫法
type 彈窗型別(toast | footer | actionsheet | actionsheetPicker | android | ios)
popupStyle 自定義彈窗樣式
icon toast圖示(loading | success | fail)
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 彈窗層疊(預設8080)
teleport 指定掛載節點(預設是掛載元件標籤位置,可通過teleport自定義掛載位置) teleport="body | #xxx | .xxx"
btns 彈窗按鈕(引數:text|style|disabled|click)
++++++++++++++++++++++++++++++++++++++++++++++
|emit事件觸發|
success 層彈出後回撥(@success="xxx")
end 層銷燬後回撥(@end="xxx")
++++++++++++++++++++++++++++++++++++++++++++++
|event事件|
onSuccess 層開啟回撥事件
onEnd 層關閉回撥事件
v3popup同樣的支援函式式+元件式兩種方式。
- 函式式
let $el = this.$v3popup({ title: '標題', content: '<div style='color:#f90;padding:10px;'>這裡是內容資訊!</div>', type: 'android', shadeClose: false, xclose: true, btns: [ {text: '取消', click: () => { $el.close(); }}, {text: '確認', style: 'color:#09f;', click: () => handleOK}, ], onSuccess: () => {}, onEnd: () => {} })
- 元件式
<v3-popup v-model="showMsg" anim="fadeIn" content="msg提示框測試(2s後視窗關閉)" shadeClose="false" time="2" />
<v3-popup v-model="showConfirm" shadeClose="false" title="標題" xclose z-index="2021" content="<div style='color:#ff5252;padding:20px;'>確認框(這裡是確認框提示資訊,這裡確認框提示資訊,這裡是確認框提示資訊)</div>" :btns="[ {text: '取消', click: () => showConfirm=false}, {text: '確定', style: 'color:#09f;', click: handleInfo}, ]" />
v3popup元件模板及核心邏輯處理部分。
<template>
<div ref="elRef" v-show="opened" class="vui__popup" :class="{'vui__popup-closed': closeCls}" :id="id">
<!-- //蒙層 -->
<div v-if="JSON.parse(shade)" class="vui__overlay" @click="shadeClicked" :style="{opacity}"></div>
<div class="vui__wrap">
<div class="vui__wrap-section">
<div class="vui__wrap-child" :class="['anim-'+anim, type&&'popupui__'+type, round&&'round', position]" :style="[popupStyle]">
<div v-if="title" class="vui__wrap-tit" v-html="title"></div>
<div v-if="type=='toast'&&icon" class="vui__toast-icon" :class="['vui__toast-'+icon]" v-html="toastIcon[icon]"></div>
<!-- 判斷插槽是否存在 -->
<template v-if="$slots.content">
<div class="vui__wrap-cnt"><slot name="content" /></div>
</template>
<template v-else>
<div v-if="content" class="vui__wrap-cnt" v-html="content"></div>
</template>
<slot />
<div v-if="btns" class="vui__wrap-btns">
<span v-for="(btn, index) in btns" :key="index" class="btn" :style="btn.style" @click="btnClicked($event, index)" v-html="btn.text"></span>
</div>
<span v-if="xclose" class="vui__xclose" :class="xposition" :style="{'color': xcolor}" @click="close"></span>
</div>
</div>
</div>
</div>
</template>
/**
* @Desc Vue3.0自定義彈層V3Popup
* @Time andy by 2020-12
* @About Q:282310962 wx:xy190310
*/
<script>
import { onMounted, ref, reactive, watch, toRefs, nextTick } from 'vue'
let $index = 0, $locknum = 0, $timer = {}
export default {
props: {
// 接收父元件v-model值,如果v-model:open,則這裡需寫open: {...}
modelValue: { type: Boolean, default: false },
// 識別符號,相同ID共享一個例項
id: {
type: String, default: ''
},
title: String,
content: String,
type: String,
popupStyle: String,
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: '8080' },
teleport: [String, Object],
btns: {
type: Array, default: null
},
onSuccess: { type: Function, default: null },
onEnd: { type: Function, default: null },
},
emits: [
'update:modelValue'
],
setup(props, context) {
const elRef = ref(null)
const data = reactive({
opened: false,
closeCls: '',
toastIcon: {
...
}
})
onMounted(() => {
...
})
// 監聽彈層v-model
watch(() => props.modelValue, (val) => {
if(val) {
open()
}else {
close()
}
})
// 開啟彈層
const open = () => {
if(data.opened) return
data.opened = true
typeof props.onSuccess === 'function' && props.onSuccess()
const dom = elRef.value
dom.style.zIndex = getZIndex() + 1
...
// 倒數計時
if(props.time) {
$index++
// 避免重複操作
if($timer[$index] !== null) clearTimeout($timer[$index])
$timer[$index] = setTimeout(() => {
close()
}, parseInt(props.time) * 1000)
}
// 長按|右鍵選單
if(props.follow) {
...
}
}
// 關閉彈層
const close = () => {
if(!data.opened) return
data.closeCls = true
setTimeout(() => {
...
context.emit('update:modelValue', false)
typeof props.onEnd === 'function' && props.onEnd()
}, 200)
}
// 點選遮罩層
const shadeClicked = () => {
if(JSON.parse(props.shadeClose)) {
close()
}
}
// 按鈕事件
const btnClicked = (e, index) => {
let btn = props.btns[index];
if(!btn.disabled) {
typeof btn.click === 'function' && btn.click(e)
}
}
...
return {
...toRefs(data),
elRef,
close,
shadeClicked,
btnClicked,
}
}
}
</script>
大家也可以根據以上模板或邏輯自行開發出一些想要的功能。
支援類似有讚的圓角彈框效果,可自定義彈出位置及關閉按鈕位置。
vue3.0中支援createApp
或createVNode render
兩種方式來擴充套件例項函式,將彈框元件掛載到body上。
let $inst
// 建立掛載例項
let createMount = (opts) => {
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)
const app = createApp(PopupConstructor, {
...opts, modelValue: true,
remove() {
app.unmount(mountNode)
document.body.removeChild(mountNode)
}
})
return app.mount(mountNode)
}
好了,基於vue3開發移動端彈框就分享這麼多。感興趣的可以自己去動手試一試哈。?
electron+vue 仿微信客戶端聊天|electron 仿微信介面|electron 聊天例項
本作品採用《CC 協議》,轉載必須註明作者和本文連結