wangzhibo
4 天以前 10595d8632f959d0954d1939243196f4eed02372
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<template>
    <view class="msg-list">
        <view
            v-for="(d, n) in message.list"
            :key="d.id"
            class="group"
            :class="{
                'is-show': message.list.length - n <= pagination.page,
            }"
        >
            <block v-for="item in d.data" :key="item.id">
                <!-- 日期 -->
                <view class="date" v-if="item.date">
                    <text>{{ item.date }}</text>
                </view>
 
                <!-- 列表项 -->
                <msg-item :item="item" />
            </block>
        </view>
    </view>
</template>
 
<script setup lang="ts">
import { reactive, getCurrentInstance, nextTick, ref } from "vue";
import { useMessage, useScroller } from "../hooks";
import MsgItem from "./msg-item.vue";
 
const message = useMessage();
const { proxy }: any = getCurrentInstance();
const scroller = useScroller();
 
// 分页
const pagination = reactive({
    page: 1,
});
 
// 加载中
const loading = ref(false);
 
// 滚动到顶部
async function scrollToUpper() {
    if (loading.value) {
        return false;
    }
 
    loading.value = true;
 
    // 没有更多了
    if (pagination.page > message.list.length) {
        return false;
    }
 
    // 计算当前的高度
    const h1 = await getHeight();
 
    // 预加载下一页
    await message.refresh({
        page: pagination.page + 1,
    });
 
    // 下一页
    pagination.page += 1;
 
    // 延迟
    await nextTick();
 
    // 计算页数增加后的高度
    const h2 = await getHeight();
 
    // 滚动到原来的位置
    scroller.scrollTo(h2 - h1, false);
 
    // 加载完成
    loading.value = false;
}
 
// 获取高度
function getHeight(): Promise<number> {
    return new Promise((resolve) => {
        uni.createSelectorQuery()
            .in(proxy)
            .select(".msg-list")
            .boundingClientRect((rect) => {
                resolve(rect?.height || 0);
            })
            .exec();
    });
}
 
// 监听滚动
function onScroll(scrollTop: number) {
    if (scrollTop < 5) {
        scrollToUpper();
    }
}
 
defineExpose({
    onScroll,
});
</script>
 
<style lang="scss" scoped>
.msg-list {
    padding: 24rpx;
 
    .group {
        opacity: 0;
        height: 0;
        overflow: hidden;
        transition: opacity 0.3s;
 
        &.is-show {
            height: auto;
            opacity: 1;
        }
    }
 
    .date {
        margin: 20rpx;
        text-align: center;
 
        text {
            background-color: #c9c9c9;
            padding: 10rpx;
            border-radius: 8rpx;
            color: #fff;
            font-size: 24rpx;
        }
    }
}
</style>