vue3彈出層V3Popup實(shí)例詳解
Vue3-Popup 基于vue3構(gòu)建的手機(jī)端自定義彈層組件。
一款集合了msg、alert、dialog、modal、actionSheet、toast等多種效果的Vue3自定義彈層組件。支持上下左右彈出、圓角、自定義彈層樣式、多按鈕及長(zhǎng)按/右鍵功能。
引入v3popup
// 在main.js中全局引入 import { createApp } from 'vue' import App from './App.vue' // 引入彈窗組件v3popup import V3Popup from './components/v3popup' createApp(App).use(V3Popup).mount('#app')
調(diào)用方式支持標(biāo)簽式+函數(shù)式,根據(jù)項(xiàng)目需要選擇合適的調(diào)用方法。
<!-- 提示框 --> <v3-popup v-model="showMsg" anim="fadeIn" content="msg提示框測(cè)試(3s后窗口關(guān)閉)" shadeClose="false" time="3" /> <!-- 詢(xún)問(wèn)框 --> <v3-popup v-model="showConfirm" shadeClose="false" title="標(biāo)題" xclose z-index="2020" content="<div style='color:#1be769;padding:20px;'>確認(rèn)框(這里是確認(rèn)框提示信息,這里確認(rèn)框提示信息,這里是確認(rèn)框提示信息)</div>" :btns="[ {text: '取消', click: () => showConfirm=false}, {text: '確定', style: 'color:#f90;', click: handleInfo}, ]" />
// 函數(shù)式調(diào)用 let $el = this.$v3popup({ title: '標(biāo)題', content: '<div style='color:#f90;padding:10px;'>這里是內(nèi)容信息!</div>', type: 'android', shadeClose: false, xclose: true, btns: [ {text: '取消', click: () => { $el.close(); }}, {text: '確認(rèn)', style: 'color:#f90;', click: () => handleOK}, ], onSuccess: () => {}, onEnd: () => {} })
vue3中可通過(guò) 和
兩種方式掛載類(lèi)似vue2中prototype原型鏈方法。
通過(guò) 方式掛載。
// vue2中調(diào)用 methods: { showDialog() { this.$v3popup({...}) } } // vue3中調(diào)用 setup() { // 獲取上下文 const { ctx } = getCurrentInstance() ctx.$v3popup({...}) }
通過(guò) 方式掛載。
// vue2中調(diào)用 methods: { showDialog() { this.v3popup({...}) } } // vue3中調(diào)用 setup() { const v3popup = inject('v3popup') const showDialog = () => { v3popup({...}) } return { v3popup, showDialog } }
預(yù)覽效果
v3popup參數(shù)配置
組件支持如下20+種參數(shù)靈活配置。
|props參數(shù)| v-model 是否顯示彈框 title 標(biāo)題 content 內(nèi)容(支持String、帶標(biāo)簽內(nèi)容、自定義插槽內(nèi)容)***如果content內(nèi)容比較復(fù)雜,推薦使用標(biāo)簽式寫(xiě)法 type 彈窗類(lèi)型(toast | footer | actionsheet | actionsheetPicker | android | ios) popupStyle 自定義彈窗樣式 icon toast圖標(biāo)(loading | success | fail) shade 是否顯示遮罩層 shadeClose 是否點(diǎn)擊遮罩時(shí)關(guān)閉彈窗 opacity 遮罩層透明度 round 是否顯示圓角 xclose 是否顯示關(guān)閉圖標(biāo) xposition 關(guān)閉圖標(biāo)位置(left | right | top | bottom) xcolor 關(guān)閉圖標(biāo)顏色 anim 彈窗動(dòng)畫(huà)(scaleIn | fadeIn | footer | fadeInUp | fadeInDown) position 彈出位置(top | right | bottom | left) follow 長(zhǎng)按/右鍵彈窗(坐標(biāo)點(diǎn)) time 彈窗自動(dòng)關(guān)閉秒數(shù)(1、2、3) zIndex 彈窗層疊(默認(rèn)8080) teleport 指定掛載節(jié)點(diǎn)(默認(rèn)是掛載組件標(biāo)簽位置,可通過(guò)teleport自定義掛載位置) teleport="body | #xxx | .xxx" btns 彈窗按鈕(參數(shù):text|style|disabled|click) ++++++++++++++++++++++++++++++++++++++++++++++ |emit事件觸發(fā)| success 層彈出后回調(diào)(@success="xxx") end 層銷(xiāo)毀后回調(diào)(@end="xxx") ++++++++++++++++++++++++++++++++++++++++++++++ |event事件| onSuccess 層打開(kāi)回調(diào)事件 onEnd 層關(guān)閉回調(diào)事件
vpopop.vue模板核心代碼
<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自定義彈出層組件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,則這里需寫(xiě)open: {...} modelValue: { type: Boolean, default: false }, // 標(biāo)識(shí)符,相同ID共享一個(gè)實(shí)例 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(() => { ... }) // 監(jiān)聽(tīng)彈層v-model watch(() => props.modelValue, (val) => { if(val) { open() }else { close() } }) // 打開(kāi)彈層 const open = () => { if(data.opened) return data.opened = true typeof props.onSuccess === 'function' && props.onSuccess() const dom = elRef.value dom.style.zIndex = getZIndex() + 1 ... // 倒計(jì)時(shí) if(props.time) { $index++ // 避免重復(fù)操作 if($timer[$index] !== null) clearTimeout($timer[$index]) $timer[$index] = setTimeout(() => { close() }, parseInt(props.time) * 1000) } // 長(zhǎng)按|右鍵菜單 if(props.follow) { ... } } // 關(guān)閉彈層 const close = () => { if(!data.opened) return data.closeCls = true setTimeout(() => { ... context.emit('update:modelValue', false) typeof props.onEnd === 'function' && props.onEnd() }, 200) } // 點(diǎn)擊遮罩層 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>
vue2.x中通過(guò)Vue.extends擴(kuò)展函數(shù)實(shí)例來(lái)實(shí)現(xiàn)掛載彈窗到body上。
vue3.x中則可以通過(guò) 和
來(lái)實(shí)現(xiàn)掛載到body上。
import { createApp } from 'vue' import PopupConstructor from './popup.vue' let $inst // 創(chuàng)建掛載實(shí)例 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) } function V3Popup(options = {}) { options.id = options.id || 'v3popup_' + generateId() $inst = createMount(options) return $inst } V3Popup.install = app => { app.component('v3-popup', PopupConstructor) // app.config.globalProperties.$v3popup = V3Popup app.provide('v3popup', V3Popup) }
這樣就可以實(shí)現(xiàn)函數(shù)式來(lái)調(diào)用組件了。
另外vue2.x中給v-model傳值 this.$emit('input', false)
vue3中modelValue是默認(rèn)的。 則是 context.emit('update:modelValue', false)
如果定義的是v-model:visible,則需要先在props: { visible: Boolean }中聲明,然后context.emit('update:visible': false)
Ok,基于vue3.0開(kāi)發(fā)自定義彈框組件就介紹到這里。感興趣的可以動(dòng)手去試試哈。💪🏻
到此這篇關(guān)于vue3彈出層V3Popup實(shí)例詳解的文章就介紹到這了,更多相關(guān)vue3彈出層內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入探索VueJS Scoped CSS 實(shí)現(xiàn)原理
這篇文章主要介紹了深入探索VueJS Scoped CSS 實(shí)現(xiàn)原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Vue.js bootstrap前端實(shí)現(xiàn)分頁(yè)和排序
這篇文章主要為大家詳細(xì)介紹了Vue.js結(jié)合bootstrap前端實(shí)現(xiàn)分頁(yè)和排序效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03vue框架制作購(gòu)物車(chē)小球動(dòng)畫(huà)效果實(shí)例代碼
最近在學(xué)習(xí)前端制作了一個(gè)購(gòu)物車(chē)小球的動(dòng)畫(huà)效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-09-09webpack4+express+mongodb+vue實(shí)現(xiàn)增刪改查的示例
這篇文章主要介紹了webpack4+express+mongodb+vue 實(shí)現(xiàn)增刪改查的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11關(guān)于Vue3中element-plus的el-dialog對(duì)話框無(wú)法顯示的問(wèn)題及解決方法
最近今天在寫(xiě)一個(gè)停車(chē)場(chǎng)管理系統(tǒng)的項(xiàng)目時(shí),在用vue3寫(xiě)前端時(shí),在前端模板選擇上,我一時(shí)腦抽,突然決定放棄SpringBoot,選擇了以前幾乎很少用的element-plus,然后果不其然,錯(cuò)誤連連,下面給大家分享dialog對(duì)話框無(wú)法顯示的原因,感興趣的朋友一起看看吧2023-10-10vue-cli如何修改打包項(xiàng)目結(jié)構(gòu)及前綴
這篇文章主要介紹了vue-cli如何修改打包項(xiàng)目結(jié)構(gòu)及前綴問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Vue實(shí)現(xiàn)仿iPhone懸浮球的示例代碼
這篇文章主要介紹了Vue實(shí)現(xiàn)仿iPhone懸浮球的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03