uniapp实现聊天中的接发消息自动滚动、消息定位和回到底部

发布于:2025-06-19 ⋅ 阅读:(21) ⋅ 点赞:(0)

前言

前言无需多言,想必大家对聊天软件的功能已经很熟悉, 这里不做过多赘述,笔者通过uniapp实现聊天中的接发消息自动滚动、消息定位和回到底部。

代码实现

<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>

演示

接发消息自动滚动

发送和接收消息都可以自己滚动到最新消息!
在这里插入图片描述
在这里插入图片描述

消息定位

为简化代码,消息框直接输入消息的索引号,即可定位对应消息,你可以自己添加样式!
在这里插入图片描述
在这里插入图片描述

回到底部

点击回到底部按钮即可!
在这里插入图片描述

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到