碼迷,mamicode.com
首頁 > 微信 > 詳細

基于uni-app全端彈框組件uaPopup「兼容h5+小程序+app端|nvue」

時間:2021-07-12 17:47:23      閱讀:0      評論:0      收藏:0      [點我收藏+]

標簽:cti   new   cal   ++   size   option   后臺管理系統   內心   別人   

uniapp兼容多端自定義模態彈框組件UAPopup

ua-popup 一款輕量級的uniapp自定義彈窗組件。匯集了android、ios和微信彈窗效果(msg消息、alert提示框、dialog對話框、actionsheet底部動作框、toast輕提示、長按定位菜單)等功能。

如下圖:H5+App端+小程序效果,親測多端運行一致。

技術圖片

◆ 引入使用

 ▍在main.js中引入uapopup彈框組件

// 引入自定義彈框組件
import uaPopup from ‘./components/ua-popup/index.vue‘
Vue.component(‘ua-popup‘, uaPopup)

說明:自HBuilderX 2.5.5起支持easycom組件模式。只要組件在components目錄,并且符合 components/ua-popup/ua-popup.vue 結構。則無需引入組件,直接在頁面使用即可。

技術圖片

UApopup支持標簽組件式+函數式兩種調用方式。

  • 標簽式
<!-- msg提示(自定義背景) -->
<ua-popup
    v-model="showMsgBg"
    anim="footer"
    content="hello uniapp"
    shade="false"
    time="2"
    :custom-style="{‘backgroundColor‘: ‘rgba(0,0,0,.6)‘, ‘color‘: ‘#fff‘}"
/>

<!-- 詢問框 -->
<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},
    ]"
/>
  • 函數式
<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>

說明:一些簡單的提示使用函數式調用足以,如果復雜的模板展示,則推薦使用組件式調用(支持slot插槽)

  • 簡單消息提示

技術圖片

<ua-popup v-model="showMsg" anim="fadeIn" content="上善若水,水利萬物而不爭" shadeClose="false" time="3" />
  • 底部彈框效果

技術圖片

技術圖片

技術圖片

<!-- 底部對話框 -->
<ua-popup v-model="showFooter" anim="footer" type="footer" :shadeClose="false"
    content="真正覺悟的一刻,是放下追尋外在世界的財富,而開始追尋內心世界的真正財富。"
    :btns="[
        {text: ‘Get到了‘, style: ‘color:#00e0a1;‘, click: handleInfo},
        {text: ‘收藏‘, style: ‘color:#ee0a24;‘},
        {text: ‘取消‘, style: ‘color:#a9a9a9;‘, click: hideFooter},
    ]"
/>

<!-- ActionSheet底部彈出式菜單 -->
<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>
  • 輕提示loading

技術圖片

技術圖片

<ua-popup v-model="showToast" type="toast" icon="loading" time="2" content="加載中..." />
<!-- <ua-popup v-model="showToast" type="toast" icon="success" shade="false" time="2" content="成功提示" /> -->
<!-- <ua-popup v-model="showToast" type="toast" icon="fail" shade="false" time="2" content="失敗提示" /> -->
<!-- <ua-popup v-model="showToast" type="toast" icon="warn" shade="false" time="2" content="警告提示" /> -->
<!-- <ua-popup v-model="showToast" type="toast" icon="info" shade="false" time="2" content="普通提示" /> -->
  • 長按菜單效果

技術圖片

技術圖片

<!-- 長按彈窗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>

注意:需要傳入follow坐標點參數。

// 長按菜單操作
handleContextMenu1(e) {
    this.showContextMenu1 = true;
    this.follow1 = [e.touches[0].clientX, e.touches[0].clientY]
},

very nice! 是不是覺得這款插件還不錯,也是倒騰了幾個通宵搞出來的。尤其調試nvue頁面,簡直讓人有點抓狂~~??

技術圖片

◆ UApopup編碼實現

  • 支持20+參數配置
props: {
    // 接收父組件中v-model的值
    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>
    <!-- #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>

最后是運行在video頁面效果圖,完美的兼容性。

技術圖片

好了,基于uni-app開發多端自定義彈窗組件就分享到這里。希望對大家有點幫助哈!?

最后附上vue3+electron實例項目

electron+vue3跨端仿QQ聊天:https://www.cnblogs.com/xiaoyan2017/p/14454624.html

electron+vite2后臺管理系統:https://www.cnblogs.com/xiaoyan2017/p/14776441.html

技術圖片

 

基于uni-app全端彈框組件uaPopup「兼容h5+小程序+app端|nvue」

標簽:cti   new   cal   ++   size   option   后臺管理系統   內心   別人   

原文地址:https://www.cnblogs.com/xiaoyan2017/p/14993445.html

(0)
(0)
   
舉報
評論 一句話評論(0
登錄后才能評論!
? 2014 mamicode.com 版權所有  聯系我們:gaon5@hotmail.com
迷上了代碼!
4399在线看MV_久久99精品久久久久久久久久_成人又黄又爽又刺激视频_能收黄台的app不收费