uni-app中仿微信列表長按彈出選擇菜單


1、實現效果:

2、此鏈接引入uni-app插件:https://ext.dcloud.net.cn/plugin?id=678

3、view段:

<template>
    <view>
        <view class="list">
            <view class="flex_col" @longpress="onLongPress" :class="{'active':pickerUserIndex==index}" @tap="listTap" v-for="(item,index) in userList"
             :key="index" :data-index="index">
                <image src="../../static/logo.png" mode="aspectFill"></image>
                <view class="flex_grow">
                    <view class="flex_col">
                        <view class="flex_grow">{{item.name}}</view>
                        <view class="time">{{item.time}}</view>
                    </view>
                    <view class="info">{{item.info}}</view>
                </view>
            </view>
        </view>
        <view class="shade" v-show="showShade" @tap="hidePop">
            <view class="pop" :style="popStyle" :class="{'show':showPop}">
                <view v-for="(item,index) in popButton" :key="index" @tap="pickerMenu" :data-index="index">{{item}}</view>
            </view>
        </view>
    </view>
</template>

4、script段代碼:

<script>
    export default {
        data() {
            return {
                userList: [],
                /* 窗口尺寸 */
                winSize: {},
                /* 顯示遮罩 */
                showShade: false,
                /* 顯示操作彈窗 */
                showPop: false,
                /* 彈窗按鈕列表 */
                popButton: ["標為關注", "置頂聊天", "刪除該聊天"],
                /* 彈窗定位樣式 */
                popStyle: "",
                /* 選擇的用戶下標 */
                pickerUserIndex: -1
            }
        },
        onLoad() {
            this.getListData();
            this.getWindowSize();

            // #ifdef H5
            document.onLong = function(e) {
                var e = e || window.event;
                e.preventDefault();
            };
            // #endif
        },
        methods: {
            /* 列表觸摸事件 */
            listTap() {
                /* 因彈出遮罩問題,所以需要在遮罩彈出的情況下阻止列表事件的觸發 */
                if (this.showShade) {
                    return;
                }

                console.log("列表觸摸事件觸發")
            },
            /* 獲取列表數據 */
            getListData() {
                let list = [];
                for (let i = 0; i < 20; i++) {
                    list.push({
                        "name": `第${i+1}個用戶`,
                        "time": '5月20日',
                        "info": `這是第${i+1}個用戶的聊天信息`
                    })
                }
                this.userList = list;
            },
            /* 獲取窗口尺寸 */
            getWindowSize() {
                uni.getSystemInfo({
                    success: (res) => {
                        this.winSize = {
                            "witdh": res.windowWidth,
                            "height": res.windowHeight
                        }
                    }
                })
            },
            /* 長按監聽 */
            onLongPress(e) {
                let [touches, style, index] = [e.touches[0], "", e.currentTarget.dataset.index];

                /* 因 非H5端不兼容 style 屬性綁定 Object ,所以拼接字符 */
                if (touches.clientY > (this.winSize.height / 2)) {
                    style = `bottom:${this.winSize.height-touches.clientY}px;`;
                } else {
                    style = `top:${touches.clientY}px;`;
                }
                if (touches.clientX > (this.winSize.witdh / 2)) {
                    style += `right:${this.winSize.witdh-touches.clientX}px`;
                } else {
                    style += `left:${touches.clientX}px`;
                }

                this.popStyle = style;
                this.pickerUserIndex = Number(index);
                this.showShade = true;
                this.$nextTick(() => {
                    setTimeout(() => {
                        this.showPop = true;
                    }, 10);
                });
            },
            /* 隱藏彈窗 */
            hidePop() {
                this.showPop = false;
                this.pickerUserIndex = -1;
                setTimeout(() => {
                    this.showShade = false;
                }, 250);
            },
            /* 選擇菜單 */
            pickerMenu(e) {
                let index = Number(e.currentTarget.dataset.index);
                console.log(`第${this.pickerUserIndex+1}個用戶,第${index+1}個按鈕`);
                // 在這里開啟你的代碼秀

                uni.showToast({
                    title: `第${this.pickerUserIndex+1}個用戶,第${index+1}個按鈕`,
                    icon: "none",
                    mask: true,
                    duration: 600
                });

                /* 
                 因為隱藏彈窗方法中會將當前選擇的用戶下標還原為-1,
                 如果行的菜單方法存在異步情況,請在隱藏之前將該值保存,或通過參數傳入異步函數中
                 */
                this.hidePop();
            }
        }
    }
</script>

5、style代碼

<style scoped lang="scss">
    /* 列式彈性盒子 */
    .flex_col {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;
        justify-content: flex-start;
        align-items: center;
        align-content: center;
    }

    /* 彈性盒子彈性容器 */
    .flex_col .flex_grow {
        width: 0;
        -webkit-box-flex: 1;
        -ms-flex-positive: 1;
        flex-grow: 1;
    }

    .flex_row .flex_grow {
        -webkit-box-flex: 1;
        -ms-flex-positive: 1;
        flex-grow: 1;
    }

    /* 彈性盒子允許換行 */
    .flex_col.flex_wrap {
        -ms-flex-wrap: wrap;
        flex-wrap: wrap;
    }

    /* 列表 */
    .list {
        background-color: #fff;
        font-size: 28upx;
        color: #333;
        user-select: none;
        touch-callout: none;

        &>view {
            padding: 24upx 30upx;
            position: relative;

            &:active,
            &.active {
                background-color: #f3f3f3;
            }

            image {
                height: 80upx;
                width: 80upx;
                border-radius: 4px;
                margin-right: 20upx;
            }

            &>view {
                line-height: 40upx;

                .time,
                .info {
                    color: #999;
                    font-size: 24upx;
                }

                .time {
                    width: 150upx;
                    text-align: right;
                }

                .info {
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }
            }
        }

        &>view:not(:first-child) {
            margin-top: 1px;

            &::after {
                content: '';
                display: block;
                height: 0;
                border-top: #CCC solid 1px;
                width: 620upx;
                position: absolute;
                top: -1px;
                right: 0;
                transform:scaleY(0.5);    /* 1px像素 */
            }
        }
    }

    /* 遮罩 */
    .shade {
        position: fixed;
        z-index: 100;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        -webkit-touch-callout: none;

        .pop {
            position: fixed;
            z-index: 101;
            width: 200upx;
            box-sizing: border-box;
            font-size: 28upx;
            text-align: left;
            color: #333;
            background-color: #fff;
            box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
            line-height: 80upx;
            transition: transform 0.15s ease-in-out 0s;
            user-select: none;
            -webkit-touch-callout: none;
            transform: scale(0, 0);

            &.show {
                transform: scale(1, 1);
            }

            &>view {
                padding: 0 20upx;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                user-select: none;
                -webkit-touch-callout: none;

                &:active {
                    background-color: #f3f3f3;
                }
            }
        }
    }
</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM