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 };
};
相关推荐
落魄江湖行6 分钟前
基础篇九 Nuxt4 插件系统:扩展 Nuxt 能力
前端·vue.js·typescript·nuxt4
七月稻草人16 分钟前
Spring Boot + Vue 3 全栈项目,内网穿透实现 HTTPS 公网访问,前后端分离部署方案
vue.js·spring boot·https
qq_2837200510 小时前
Python Celery + FastAPI + Vue 全栈异步任务实战
vue.js·python·fastapi
吴声子夜歌12 小时前
Vue3——Vue实例与数据绑定
前端·javascript·vue.js
一 乐13 小时前
物流信息管理|基于springboot + vue物流信息管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·物流信息管理系统
孜孜不倦不忘初心15 小时前
Vue 项目结构与命名规范
vue.js·代码规范
账号已注销free16 小时前
Vue3项目中给组件命名的方式
vue.js
前端那点事16 小时前
VueUse 全面指南|Vue3组合式工具集实战
vue.js
前端那点事16 小时前
Vue3+Pinia实战完整版|从入门到精通,替代Vuex的状态管理首选
vue.js