消息会话—发送消息自动滚动到最底部

背景

在项目开发中,实现用户友好的输入交互是提升用户体验的关键之一。例如,在消息会话页面中,为了确保用户在发送新消息后页面能自动滚动到最底部,从而始终保持最新消息的可见性,需要实现自动滚动功能。这不仅提升了用户体验,还使得用户能够实时关注对话的最新进展。

实现思路

  • 监听消息列表的变化
  • 在消息变化后自动滚动到最底部

示例代码

组件结构如下

javascript 复制代码
<template>
  <div>
    <el-dialog width="68%" :visible.sync="isShow" :before-close="close" class="kefu" :show-close="false"
      :close-on-click-modal="false">
      <div class="kefu-con">
        <i class="el-icon-close close" @click="close" />
        <div class="header">
          <img :src="kefuImg" alt="">
          <div class="title">小奶龙智能问答助手</div>
        </div>
        <div class="container" ref="container">
          <div class="content" ref="content">
            <div v-for="item in messageForm">
              <div class="reply-container" v-if="item.type === 'reply'">
                <div class="reply-content">
                  <div class="img-con">
                    <img :src="kefuImg" alt="">
                  </div>
                  <div class="reply" @click="handleProxyClick">
                    <div v-if="item.isXml" v-html="item.content"></div>
                    <p v-else>
                      {{ item.content }}
                    </p>
                  </div>
                </div>
              </div>
              <div class="qs-container" v-if="item.type === 'qs'">
                <div class="qs-content">
                  <div class="qs">
                    <p>
                      {{ item.content }}
                    </p>
                  </div>
                </div>
              </div>
            </div>
          </div>

        </div>
        <div class="footer">
          <img :src="kefuImg" alt="">
          <div class="question-con">
            <el-input class="ipt" v-model="question" placeholder="请输入想咨询的问题"></el-input>
            <el-button class="btn" type="warning" round @click="send">发送</el-button>
          </div>

        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { getAnswer } from '@/api/checkin.js';
export default {
  data() {
    return {
      isShow: false,
      kefuImg: require("@/assets/images/headshot.png"),
      question: '',
      messageForm: [{
        content: "<p>您好, 我是您的小奶龙,你的智能助手。 你可以问我编码相关的问题,也可以一起更高效、更高质量地完成编码工作。比如 "<span class='quick' style='color: #5094d5;cursor: pointer;' @click='quick'>动态路由实现</span>", "<span class='quick' style='color: #5094d5;cursor: pointer;' @click='quick'>移动端适配</span>" 等等一些问题。</p>",
        type: "reply", // reply 回答  qs 问题
        isXml: true,
      },
      {
        content: '动态路由实现',
        type: "qs", // reply 回答  qs 问题
        isXml: false,
      }
      ]
    }
  },
  methods: {
    handleProxyClick(event) {
      // 获取触发事件的目标元素  event 事件对象
      const target = event.target;
      // 判断目标元素是否包含指定类名
      if (target.classList.contains('quick')) {
        // 传递目标元素的文本内容
        this.quick(target.outerText);
      }
    },
    quick(text) {
      console.log('quick方法触发了::: ');
      this.question = text;
      // 发送
      this.send();
    },
    show() {
      this.isShow = true;
    },
    close() {
      this.isShow = false;
    },
    send() {
      let NewQuestion = this.question.trim();
      if (NewQuestion === '') {
        return;
      }
      this.messageForm.push({
        content: NewQuestion,
        type: 'qs',
        isXml: false,
      });
      setTimeout(() => {
        this.question = '';
      })
    },
  },
}
</script>

发送消息不滚动到最底部

解决方法

获取对话框内容 DOM 元素,将滚动容器的滚动条位置设置为其最大高度,从而使滚动容器自动滚动到最底部

container.scrollTop

  • 获取当前滚动容器的垂直滚动距离。

  • 设置 scrollTop 的值可以改变滚动容器的滚动位置。

  • 如果 scrollTop 设置为 0,则滚动到顶部;如果设置为某个较大的值,则滚动到对应的位置。

container.scrollHeight

  • 获取滚动容器的总高度(包括不可见部分)。

  • scrollTop 设置为 scrollHeight 时,滚动容器会滚动到最底部。

javascript 复制代码
 // 获取内容容器
const content = this.$refs.content;

this.$refs.container.scrollTo(0, content.scrollHeight);

效果如下

当异步接口返回时,插入的内容不会滚动到最底部,我们需要使用 this.$nextTick() 函数,该函数会等待 DOM 更新完成后才调用

javascript 复制代码
export default {
  methods: {
    send() {
      let NewQuestion = this.question.trim();
      if (NewQuestion === '') {
        return;
      }
      this.messageForm.push({
        content: NewQuestion,
        type: 'qs',
        isXml: false,
      });
      setTimeout(() => {
        // 模拟异步请求
        this.messageForm.push({
          content: '11111',
          type: 'reply',
          isXml: false,
        });
        this.question = '';
        this.$nextTick(() => {
          // 滚动到底部
          this.scrollToBottom();
        })
      })
    },
    scrollToBottom() {
      const content = this.$refs.content;
      this.$refs.container.scrollTo(0, content.scrollHeight);
    }
  }
}

效果如下

总结

在设计实现消息会话页面时,为确保每次发送新消息后,页面自动滚动至底部,关键在于利用 Vue 的响应式特性结合 DOM 操作技巧。具体策略为:当消息列表数据更新后,利用 this.$nextTick() 确保 DOM 已完成更新,随后设置容器的 scrollTop 属性等于 scrollHeight,从而使页面平滑地滚动到消息区域的最底部,以此提升用户体验,保证用户始终能便捷地查看最新的聊天内容。

相关推荐
混迹网络的权某12 分钟前
每天一道C语言精选编程题之求数字的每⼀位之和
c语言·开发语言·考研·算法·改行学it·1024程序员节
IronmanJay3 小时前
【LeetCode每日一题】——862.和至少为 K 的最短子数组
数据结构·算法·leetcode·前缀和·双端队列·1024程序员节·和至少为 k 的最短子数组
加载中loading...4 小时前
Linux线程安全(二)条件变量实现线程同步
linux·运维·服务器·c语言·1024程序员节
Wx120不知道取啥名4 小时前
C语言之长整型有符号数与短整型有符号数转换
c语言·开发语言·单片机·mcu·算法·1024程序员节
biomooc5 小时前
R语言 | paletteer包:拥有2100多个调色板!
r语言·数据可视化·1024程序员节
Hello.Reader5 小时前
FFmpeg 深度教程音视频处理的终极工具
ffmpeg·1024程序员节
Y.O.U..6 小时前
STL学习-容器适配器
开发语言·c++·学习·stl·1024程序员节
就爱敲代码6 小时前
怎么理解ES6 Proxy
1024程序员节
憧憬一下6 小时前
input子系统的框架和重要数据结构详解
arm开发·嵌入式·c/c++·1024程序员节·linux驱动开发
三日看尽长安花6 小时前
【Tableau】
1024程序员节