Vue 聊天列表滚动方案

目前只实现了自动滚动到底部。还未实现下拉加载更多。如果需要在滚动触顶时加载更多,同时保持滚动位置,可能需要更加复杂的方案。

  1. 初始化时自动滚动到底部。
  2. 当列表内容变化时,如果用户当前位置接近底部且未向上滚动,则自动滚动到底部。
  3. 如果用户正在浏览上方内容,则保持当前滚动位置。
typescript 复制代码
import { useResizeObserver, useScroll, whenever } from "@vueuse/core";

export type MaybeHTMLElement = MaybeRefOrGetter<HTMLElement | null | undefined>;
/**
 * 聊天滚动组合函数
 * @param options - 配置选项
 * @param options.scrollTarget - 滚动容器元素
 * @param options.listElement - 列表内容元素,用于监听尺寸变化
 * @returns 包含滚动到底部方法的对象
 * @remarks
 * 该函数提供智能滚动行为:
 * 1. 初始化时自动滚动到底部
 * 2. 当列表内容变化时,如果用户当前位置接近底部且未向上滚动,则自动滚动到底部
 * 3. 如果用户正在浏览上方内容,则保持当前滚动位置
 */
export const useChatScroll = (options: {
  scrollTarget: MaybeHTMLElement;
  listElement: MaybeHTMLElement;
}) => {
  const scrollTarget = computed(() => toValue(options.scrollTarget));
  const { directions } = useScroll(scrollTarget);
  /**
   * 滚动到底部
   * @param options - 滚动选项
   * @param options.behavior - 滚动行为,"auto" 为瞬间滚动,"smooth" 为平滑滚动
   */
  const scrollToBottom = (options?: { behavior?: "auto" | "smooth" }) => {
    if (!scrollTarget.value) return;
    scrollTarget.value.scrollTo({
      top: scrollTarget.value.scrollHeight,
      behavior: options?.behavior,
    });
  };

  /**
   * 当滚动容器元素被挂载后,自动滚动到底部
   */
  whenever(scrollTarget, () => {
    const timer = setInterval(scrollToBottom, 60);
    // 持续滚动 1 秒
    setTimeout(() => clearInterval(timer), 1000);
  });

  /**
   * 当滚动条距离底部的距离小于该值时,会自动滚动到底部
   */
  const BOTTOM_THRESHOLD = 100;

  const listElement = computed(() => toValue(options.listElement));
  useResizeObserver(listElement, () => {
    if (!scrollTarget.value) return;
    const { scrollHeight, scrollTop, clientHeight } = scrollTarget.value;
    const scrollBottom = scrollHeight - scrollTop - clientHeight;
    // 如果正在浏览上方内容,则跳过
    if (scrollBottom > BOTTOM_THRESHOLD) return;
    // 如果正在向上方滚动,则跳过
    if (directions.top) return;
    // 正常情况,自动滚动到底部
    scrollToBottom({ behavior: "smooth" });
  });

  return { scrollToBottom };
};
相关推荐
qwfy13 小时前
我要用 AI-native 架构,从零重建一套制造业 ERP/MES
vue.js·spring boot·架构
dsyyyyy110113 小时前
Vue 3 Watch 监视完全指南
前端·javascript·vue.js
瞬时出道14 小时前
AI 回答为什么能一个字一个字蹦出来?前端搞懂 SSE 这一篇就够了
vue.js
u01110267515 小时前
Vue 3 实现图片裁剪框:拖动、缩放与固定宽高比
前端·javascript·vue.js
小小善后师16 小时前
用 Canvas + AI 实现登录页的 Logo 粒子动画
前端·vue.js
web打印社区18 小时前
远程打印:WebSocket 与 HTTP 轮询怎么选
前端·vue.js·websocket·网络协议·http·electron·pdf
朱 欢 庆20 小时前
el-table-v2 虚拟表格组件
前端·javascript·vue.js
今年下半年1 天前
【VUE】整合腾讯地图、自定义区域边界、村委名称及资产统计(放大显示资产点位)
前端·javascript·vue.js
今年下半年1 天前
【前端】ant-design-vue 表格「行、列都动态」的处理方案
前端·javascript·vue.js
志尊宝2 天前
Vue3 零基础每日笔记(054):Pinia 三件套详解——state / getters / actions 全搞懂
前端·javascript·vue.js·vue·前端开发