前言
前言无需多言,想必大家对聊天软件的功能已经很熟悉, 这里不做过多赘述,笔者通过uniapp实现聊天中的接发消息自动滚动、消息定位和回到底部。
代码实现
xml
<template>
<view class="chat-container">
<!-- 消息列表 -->
<scroll-view
class="message-list"
scroll-y
style="height: 300px;"
upper-threshold="200"
:scroll-into-view="'message-item-' + scrollMsgIdx"
:scroll-with-animation="true"
@scroll="handleScroll"
>
<view class="message-item-box" v-for="(item, idx) in chatMessageList" :key="item.id" :id="'message-item-' + idx">
<view :class="['message-item', item.self === true ? 'right' : 'left']">
<view class="message-content">
{{ item.content }}
</view>
</view>
</view>
</scroll-view>
<view class="back-to-bottom-btn" @click="scrollToBottom" v-if="showBackBottomBtn">
回到底部
</view>
<!-- 输入区域 -->
<view class="content-area">
<view class="input-box">
<textarea v-model="inputText" placeholder="输入内容" maxlength="500" auto-height/>
</view>
<button class="send-btn" @click="sendMsg" size="mini">发送</button>
<button class="jump-btn" @click="jumpMsg" size="mini">定位</button>
</view>
</view>
</template>
<script setup>
import {onLoad} from '@dcloudio/uni-app';
import {nextTick, ref} from "vue";
const scrollMsgIdx = ref(0); // 滚动控制
const showBackBottomBtn = ref(false); // 回到底部按钮显示
const inputText = ref(''); // 输入文本
const chatMessageList = ref([
{id: 0, content: '请求添加你为好友?', self: false},
{id: 1, content: '你好', self: false},
{id: 2, content: '你是谁啊?', self: true},
{id: 3, content: '我是你爸爸啊', self: false},
{id: 4, content: '???', self: true},
{id: 5, content: '我是你爷爷', self: true},
{id: 6, content: '你真的是个老六', self: false},
{id: 7, content: '谁让你张口就来', self: true},
{id: 8, content: '再问一遍你是谁?', self: true},
{id: 9, content: '我是张三,你叔叔介绍的相亲对象', self: false},
{id: 10, content: '哦哦', self: true},
{id: 11, content: '那你今年多大了?', self: true},
{id: 12, content: '27', self: false},
{id: 13, content: '那你哪个学校毕业的啊?', self: true},
{id: 14, content: '在哪里工作?', self: true},
{id: 15, content: '毕业于家里蹲大学', self: false},
{id: 16, content: '现在没工作', self: false},
{id: 17, content: '啊?那你用钱了怎么办啊', self: true},
{id: 18, content: '你管我啊', self: false},
{id: 19, content: '那你自己看着办吧!', self: true},
{id: 20, content: '好的', self: false},
{id: 21, content: '不用你操心哦', self: false},
{id: 22, content: '替你家长操心!', self: true},
{id: 23, content: '那也不需要', self: false},
{id: 24, content: '你大学学的啥啊?工作都找不到', self: true},
{id: 25, content: '大学光挂科去了', self: false},
{id: 26, content: '那怪不得', self: true},
{id: 27, content: '好自为之吧', self: true},
]); // 消息列表
onLoad(() => {
// 回到底部
scrollToBottom();
});
// 发送消息
function sendMsg() {
if (!inputText.value.trim()) {
console.log('不能发送空白信息');
return;
}
chatMessageList.value.push({id: Date.now(), content: inputText.value, self: true});
inputText.value = '';
chatMessageList.value.push({id: Date.now(), content: '自动回复', self: false});
// 回到底部
scrollToBottom();
}
// 跳转指定消息
function jumpMsg() {
if (!inputText.value.trim()) {
console.log('不能发送空白信息');
return;
}
scrollToMsgIdx(Number(inputText.value));
inputText.value = '';
}
// 滚动事件处理
function handleScroll(e) {
const { scrollTop, scrollHeight } = e.detail;
const screenHeight = uni.getSystemInfoSync().screenHeight;
showBackBottomBtn.value = scrollHeight - screenHeight - scrollTop > 50;
}
// 滚动到底部
function scrollToBottom() {
let length = chatMessageList.value.length;
if (length > 0) {
scrollToMsgIdx(length - 1);
}
}
// 滚动到指定消息
function scrollToMsgIdx(idx) {
nextTick(() => {
scrollMsgIdx.value = (idx < 0 || idx > chatMessageList.value.length - 1) ? 0 : idx;
showBackBottomBtn.value = chatMessageList.value.length - 1 - scrollMsgIdx.value > 0;
});
}
</script>
<style lang="scss" scoped>
.chat-container {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #f5f5f5;
.message-list {
flex: 1;
margin-top: 10px;
overflow: auto;
background-color: #f5f5f5;
.message-item-box {
margin: 10px;
}
.message-item {
display: flex;
&.left {
justify-content: flex-start;
.message-content {
margin-left: 10px;
background-color: #fff;
}
}
&.right {
justify-content: flex-end;
.message-content {
margin-right: 10px;
background-color: #95ec69;
}
}
.message-content {
max-width: 70%;
border-radius: 2px;
box-sizing: border-box;
word-break: break-word;
height: auto;
padding: 10px;
}
}
}
.content-area {
display: flex;
align-items: center;
padding: 8px 10px;
background-color: #fff;
border-top: 1px solid #eee;
.input-box {
flex: 4;
textarea {
box-sizing: border-box;
width: 100%;
background-color: #f5f5f5;
border-radius: 4px;
padding: 8px;
font-size: 14px;
}
}
.send-btn {
flex: 1;
text-align: center;
align-items: center;
background-color: #07c160;
color: #ffffff;
font-size: 12px;
padding: 2px !important;
}
.jump-btn {
flex: 1;
text-align: center;
align-items: center;
background-color: #97aca1;
color: #ffffff;
font-size: 12px;
padding: 2px !important;
}
}
.back-to-bottom-btn {
position: fixed;
bottom: 55px;
right: 10px;
background-color: #575859;
color: #ffffff;
padding: 5px;
border-radius: 4px;
font-size: 12px;
z-index: 999;
}
}
</style>
演示
接发消息自动滚动
发送和接收消息都可以自己滚动到最新消息!
消息定位
为简化代码,消息框直接输入消息的索引号,即可定位对应消息,你可以自己添加样式!
回到底部
点击回到底部按钮即可!
