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

背景

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

实现思路

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

示例代码

组件结构如下

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,从而使页面平滑地滚动到消息区域的最底部,以此提升用户体验,保证用户始终能便捷地查看最新的聊天内容。

相关推荐
学传打活1 天前
【边打字.边学昆仑正义文化】_进阶篇5 宇宙星系的运转(续3)
微信公众平台·1024程序员节·汉字·昆仑正义文化
学传打活6 天前
【边打字.边学昆仑正义文化】_进阶篇5 宇宙星系的运转(续1)
微信公众平台·1024程序员节·汉字·昆仑正义文化
fangzhanpeng16814 天前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
无己心17 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u01030552722 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u01030552723 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝24 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552724 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552725 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u0103055271 个月前
Java实用类应用精讲
人工智能·1024程序员节