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 };
};
相关推荐
FungLeo10 小时前
成为全栈·Vue 管理后台篇·分类树与标签管理:层级数据如何落到管理界面
前端·javascript·vue.js·分类树·naive ui·标签管理·前端数据结构
ruanno_top14 小时前
选中一项后,焦点掉回了页面顶部:三个弹层的焦点还原
vue.js
tryCbest16 小时前
Vue3——第 17 篇:模板引用(ref)与组件实例——操作 DOM 的正确姿势
vue.js·前端搭建
头发还在的女程序员17 小时前
Java在线租房系统源码解析:Spring Boot+Vue 3+UniApp房源管理与预约看房方案
java·vue.js·spring boot·租房小程序·租房系统·租房软件
FYKJ_201017 小时前
springboot同人周边订单管理系统48955-计算机毕业设计、课程设计
java·javascript·vue.js·spring boot·django·php·课程设计
梯度下降者1 天前
Nuxt框架
vue.js·服务端渲染·全栈开发·混合渲染·nuxt框架
yuyuxun11 天前
协同过滤的校园二手物品智能推荐系统的设计与实现 毕业设计-附源码40082
javascript·vue.js·spring boot·python·数据分析·django·课程设计
FungLeo2 天前
成为全栈·Vue 管理后台篇·编辑器图片上传:从文件选择到文章附件关联
前端·vue.js·编辑器·markdown·文件上传·formdata·附件管理
码云社区2 天前
智慧物业系统选型指南:房屋档案、账单管理与报修协作
前端·javascript·vue.js·智慧物业
ruanno_top2 天前
表单重置后,验证码还显示已通过:Vue 受控组件的 3 种假同步
vue.js