引言
在我參與智能問答項目中一個智能體回話并不會像豆包一樣,每次新建會話都是是從頭開始,而項目中你想創建新會話就像chatbox一樣,是點擊橡皮擦開啟新的聊天上下文,但是直接的聊天記錄依然存在,針對超過十萬+條對話數據進行展示。會出現頁面卡死的問題。
所以我們可以通過虛擬列表
的形式展示我們的對話內容
<template><div class="container"><!-- 展示問答內容 --><div class="chat-container" ref="chatContainer" @scroll="handleScroll"><!-- 優化后 --><divclass="virtual-placeholder":style="{ height: `${chatListHeight}px` }"></div><divclass="truth-box":style="{ transform: `translateY(${scrollTop}px)` }"><divclass="chat-item-container":style="{ transform: `translateY(${scrollTopItem}px)` }"><divv-for="(item, index) in renderedItems":key="index"class="chat-item":style="{ height: `${item.height}px` }"><div v-if="item.isUser" class="user-message">{{ item.content }}</div><div v-else class="system-message">{{ item.content }}</div></div></div></div><!-- ------------------------------------------- --><!-- 優化前 --><!-- <divv-for="(item, index) in chatList":key="index"class="chat-item":style="{ height: `${item.height}px` }"><div v-if="item.isUser" class="user-message">{{ item.content }}</div><div v-else class="system-message">{{ item.content }}</div></div> --></div><!-- 輸入框與發送按鈕 --><el-row type="flex" justify="center"><el-col :span="18"><el-input v-model="inputValue" placeholder="請輸入內容"></el-input></el-col><el-col :span="6"><el-button type="primary" @click="send">發送</el-button></el-col></el-row></div>
</template><script>
export default {data() {return {inputValue: '',chatList: [],startIndex: 0,visibleCount: 20, // 可視區域內顯示的條目數itemHeight: 100, // 假設每個條目平均高度為 100pxscrollTop: 0,}},computed: {chatListLength() {return this.chatList.length},chatListHeight() {return ((this.chatList.reduce((acc, item) => acc + item.height, 0) *this.chatListLength) /this.chatListLength)},renderedItems() {console.log('renderedItems', this.startIndex)return this.chatList.slice(this.startIndex,this.startIndex + this.visibleCount)},startOffset() {return this.chatList.slice(0, this.startIndex).reduce((acc, item) => acc + item.height, 0)},scrollTopItem() {return this.startOffset - this.scrollTop},},mounted() {this.chatList = new Array(100000).fill(0).map(() => {return {isUser: Math.random() > 0.5,content: '歡迎來到我們的幫助中心!',height: Math.random() * 100 + 50,}})},methods: {send() {if (this.inputValue.trim() !== '') {// 添加用戶的輸入到聊天列表this.chatList.push({isUser: true,content: this.inputValue,height: Math.random() * 100 + 50,})// 模擬系統回復setTimeout(() => {this.chatList.push({isUser: false,content: '你可以通過點擊設置選項來修改賬戶信息。',height: Math.random() * 100 + 50,})}, 500)// 清空輸入框this.inputValue = ''// 自動滾動到底部this.scrollToBottom()}},handleScroll() {const scrollTop = this.$refs.chatContainer.scrollTopthis.scrollTop = scrollToplet currentStartIndex = 0let totalHeiight = 0for (let i = 0; i < this.chatList.length; i++) {const item = this.chatList[i]totalHeiight += item.heightif (totalHeiight >= scrollTop) {currentStartIndex = ibreak}}this.startIndex = currentStartIndex >= 0 ? currentStartIndex : 0},scrollToBottom() {this.$nextTick(() => {const container = this.$refs.chatContainer// 正確設置滾動到底部container.scrollTop = container.scrollHeight})},},
}
</script>
<style lang="scss" scoped>
.container {display: flex;flex-direction: column;height: 100%;
}
.chat-container {flex: 1;height: 0;overflow-y: auto;position: relative;.truth-box {width: 100%;position: absolute;top: 0;left: 0;overflow: hidden;height: 100%;}
}
.chat-item-container {position: absolute;top: 0;left: 0;width: 100%;
}
.chat-item {
}.user-message {text-align: right;color: #409eff; // Element UI 藍色background: pink;height: 100%;
}.system-message {height: 100%;text-align: left;color: #67c23a; // Element UI 綠色background: gray;
}
</style>