MessageList State

最近更新时间:2025-09-12 18:14:52

我的收藏

MessageListState 概述

MessageListState 是一个与消息列表构建相关的状态管理中心,专为 Vue3 应用设计,用于管理消息列表的状态和操作。它利用 Vue3 的响应式系统,提供了消息列表的数据管理、分页加载、阅读回执设置、滚动控制等核心功能,是构建高性能、可定制聊天界面的重要工具。
MessageListState 采用了 Vue3 的 Composition API 和响应式设计,能够自动监听底层数据变化并更新组件状态,同时提供了丰富的业务操作方法来满足不同的使用场景。

什么时候需要 MessageListState?

当目前的 MessageList 组件能力无法满足您的特定需求,或者您希望基于底层数据重新开发一个自定义的消息列表时,可以使用 useMessageListState() 组合式函数来获取原始的数据源和相关的操作方法,进而进行灵活的定制和开发。

属性列表

字段
类型
描述
Ref<readonly MessageModel[] | undefined>
消息列表数据
Ref<boolean | undefined>
是否还有更多历史消息可加载
Ref<boolean | undefined>
是否启用阅读回执功能
Ref<boolean | undefined>
是否禁用滚动
() => Promise<void>
加载更多历史消息的方法
自动更新 messageListhasMoreOlderMessage 状态
(isDisableScroll: boolean) => void
设置滚动状态的方法
(enableReadReceipt: boolean | undefined) => void
设置阅读回执状态的方法

属性详细说明

messageList

类型:Ref<readonly MessageModel[] | undefined>
详细说明:当前会话的消息列表数据。这是一个只读的响应式数组,包含了所有已加载的消息对象。每个消息对象包含消息内容、发送者信息、时间戳、状态等完整信息。没有激活会话时,该值为 undefined

hasMoreOlderMessage

类型:Ref<boolean | undefined>
详细说明:标识是否还有更多的历史消息可以加载。当值为 true 时,表示还有更早的消息可以通过 loadMoreOlderMessage 方法获取;当值为 false 时,表示已经加载了所有历史消息;当值为 undefined 时,表示加载状态未确定。

enableReadReceipt

类型:Ref<boolean | undefined>
详细说明:控制是否启用已读回执功能。这是一个响应式引用,当设置为 true 时,发送的消息会要求对方回执已读;当设置为 false 时,不要求对方发送已读回执;默认值为 false。注:该字段仅为一个布尔值,代表需要已读回执,要实现已读回执,发送消息时需要消费该字段。

isDisableScroll

类型:Ref<boolean | undefined>
详细说明:控制消息列表的滚动行为。这是一个响应式引用,当设置为 true 时,禁用自动滚动功能;当设置为 false 时,允许正常滚动。通常在用户手动滚动查看历史消息时设置为 true,避免新消息到达时自动滚动影响用户体验。该字段的设置不会禁用页面的滚动,请在 dom 侧使用该字段控制。

loadMoreOlderMessage

类型:() => Promise<void>
详细说明:异步加载更多历史消息的方法。调用该方法会向服务器请求更早的消息数据,并自动更新 messageListhasMoreOlderMessage 状态。

setEnableReadReceipt

类型:(enableReadReceipt: boolean | undefined) => void
详细说明:用于设置阅读回执功能开关的方法。接收一个布尔值或 undefined 参数来控制是否启用阅读回执。

setIsDisableScroll

类型(isDisableScroll: boolean) => void
详细说明:用于设置滚动状态的方法。接收一个布尔值参数来控制是否禁用滚动功能。

使用示例

以下是一个完整的 MessageList 组件示例,展示了如何使用 messageListhasMoreOlderMessageloadMoreOlderMessage 来构建一个具有分页加载功能的消息列表:
<template>
<div :class="['im-message-list-container']">
<!-- 消息列表 -->
<div ref="messageListRef" class="message-list" @scroll="handleScroll">
<div v-for="message in messageList" :key="message.ID" class="message-item">
<div class="message-sender">{{ message.nick || message.from }}</div>
<div class="message-content">
<span v-if="message.type === MessageType.TEXT" class="text-message">{{ message.payload.text }}</span>
<span v-else-if="message.type === MessageType.IMAGE" class="image-message">This is an image message</span>
<span v-else-if="message.type === MessageType.CUSTOM" class="custom-message">This is a custom message</span>
<span v-else>other message</span>
</div>
<div class="message-time">
{{ new Date(message.time * 1000).toLocaleTimeString() }}
</div>
</div>
</div>

<!-- 空状态 -->
<div v-if="!messageList || messageList?.length === 0" class="empty-state">
暂无消息
</div>
</div>
</template>

<script lang="ts" setup>
import { ref, watch, onMounted, nextTick } from 'vue';
import { useMessageListState, MessageType } from '@tencentcloud/chat-uikit-vue3';

const {
messageList,
hasMoreOlderMessage,
loadMoreOlderMessage,
isDisableScroll,
setIsDisableScroll,
} = useMessageListState();

const isLoading = ref(false);
const messageListRef = ref<HTMLDivElement | null>(null);
const prevScrollHeight = ref(0);

// 加载更多消息
const handleLoadMore = async () => {
if (isLoading.value || !hasMoreOlderMessage.value) {
return;
}

isLoading.value = true;
try {
// 记录当前滚动高度
if (messageListRef.value) {
prevScrollHeight.value = messageListRef.value.scrollHeight;
}

await loadMoreOlderMessage();
} catch (error) {
console.error('加载更多消息失败:', error);
} finally {
isLoading.value = false;
}
};

// 处理滚动事件
const handleScroll = (e: Event) => {
const target = e.target as HTMLDivElement;
const { scrollTop, scrollHeight, clientHeight } = target;

// 检测是否滚动到顶部,触发加载更多
if (scrollTop === 0 && hasMoreOlderMessage.value && !isLoading.value) {
handleLoadMore();
}

// 检测用户是否在查看历史消息
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
setIsDisableScroll(!isAtBottom);
};

// 保持滚动位置(加载更多消息后)
watch(messageList, () => {
nextTick(() => {
if (messageListRef.value && prevScrollHeight.value > 0) {
const newScrollHeight = messageListRef.value.scrollHeight;
const scrollDiff = newScrollHeight - prevScrollHeight.value;
messageListRef.value.scrollTop = scrollDiff;
prevScrollHeight.value = 0;
}
});
});

// 自动滚动到底部(新消息到达时)
watch([messageList, isDisableScroll], () => {
nextTick(() => {
if (messageListRef.value && !isDisableScroll.value) {
messageListRef.value.scrollTop = messageListRef.value.scrollHeight;
}
});
});

onMounted(() => {
// 初始加载完成后滚动到底部
nextTick(() => {
if (messageListRef.value) {
messageListRef.value.scrollTop = messageListRef.value.scrollHeight;
}
});
});
</script>

<style scoped lang="scss">
.im-message-list-container {
display: flex;
flex-direction: column;
flex: 1 1 auto;
overflow: auto hidden;
height: 100%; // Ensure container has a height

.message-list {
flex: 1;
overflow-y: auto;
min-height: 0; // Important for flex container with overflow
padding: 10px;

.message-item {
margin-bottom: 15px;
padding: 10px;
background: #f5f5f5;
border-radius: 8px;

.message-sender {
font-weight: bold;
color: #333;
margin-bottom: 5px;
}

.message-content {
color: #666;
line-height: 1.5;
margin-bottom: 5px;
}

.message-time {
font-size: 12px;
color: #999;
text-align: right;
}
}
}

.empty-state {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
color: #999;
font-size: 14px;
}
}
</style>
示例效果图:

这个示例展示了如何:
使用 messageList 渲染消息列表。
调用 loadMoreOlderMessage 实现滚动到顶部自动加载历史消息。
结合 isDisableScrollsetIsDisableScroll 优化滚动体验。
处理加载状态和空状态的显示。

扩展资料

MessageModel 类型常用字段:
// MessageModel 接口定义,详细内容请参考 @tencentcloud/chat-uikit-engine 文档
// 这是一个复杂的消息模型,包含消息ID、类型、发送者、内容、时间、状态等属性。
// 示例结构 (非完整定义):
interface MessageModel {
ID: string;
conversationID: string;
type: MessageType;
payload: any;
flow: 'in' | 'out';
from: string;
to: string;
time: number; // Unix 时间戳 (秒)
status: 'unSend' | 'success' | 'fail';
isDeleted: boolean;
isRevoked: boolean;
hasRiskContent: boolean; // 是否包含风险内容
// ... 其他属性
}

MessageModel 的完整内容请参考:TUIChatEngine 参考文档

相关文档

交流与反馈

如遇任何问题,可联系 官网售后 反馈,享有专业工程师的支持,解决您的难题。