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 };
};
相关推荐
卤蛋fg644 分钟前
vue 下拉树组件 vxe-table-select 实现分页多选
vue.js
u0111026754 小时前
Vue 页面离开后还在轮询?统一清理计时器、监听器与观察器
前端·javascript·vue.js
大猩猩X5 小时前
vue 表格组件 vxe-table 实现多行编辑,支持增删改查与校验
前端·javascript·vue.js·vxe-table
ss2735 小时前
基于springboot+vue+mysql「校园二手教材循环交易」小程序,三端全跑通
vue.js·spring boot·mysql
冒险的豆子6 小时前
Proxy & Vue 响应式(合并精简版,适合面试)
前端·javascript·vue.js
Java后端的Ai之路7 小时前
前端技术Vue-18-视图中的渲染
前端·javascript·vue.js
濮水大叔17 小时前
函数式与对象式:前端架构的两种成本曲线
vue.js·react.js·函数式编程
vx_Biye_Design18 小时前
django房屋租赁推荐系统78455-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·express
林恒smileZAZ19 小时前
浏览器为什么加载不了超大图片
前端·vue.js·html5
Java后端的Ai之路1 天前
前端技术Vue-13-安装webpack与vuejs
前端·vue.js·webpack