流式输出页面滚动

流程梳理
image.png

流程中的操作有三类。

  • 页面自动滑动
  • 用户手动滑动
  • 点击按钮滑到底部
import { useState, useEffect, useRef } from 'react';
import toDown from '@/images/toDown.svg';

export default function DropFun() {
  // 显示内容 dom
  const chatContainerRef = useRef<any>(null);
  
  // 流式输出内容
  const [chatList, chatList] = useState<any[]>([]);
  // 是否显示 滑到底部 按钮
  const [dropDisplay, setDropDisplay] = useState(false);
  
  // 可视区域滚动到底部
  const dropDown = () => {
    const containerHeight = chatContainerRef.current.scrollHeight;
    
    setTimeout(() => {
      chatContainerRef.current.scrollTop = containerHeight;
    }, 0)
  }
  
  // 对话发起请求,流式返回数据
  const handleSend = () => {
    setAutoDrop(true);
    //...
  }
  
  // 每次渲染页面高度的变化后,监听滚动的变化
  useEffect(() => {
    if (chatContainerRef) {
      const viewHeight = document.documentElement.clientHeight || document.body.clientHeight;

      chatchatContainerRef.current.addEventListener('scroll', (e: any) => {
        const curHeight = e.target.scrollHeight - e.target.scrollTop;
        // 当本次距离顶部距离小于上次距离顶部距离,则可判断用户在向上滑动,停止页面自动滑动
        if (e.target.scrollTop <= lastScrollTop) {
          setAutoDrop(false);
        }

        // 记录上一次滑动距顶部距离
        lastScrollTop = e.target.scrollTop;
                
        // 当页面高度大于窗口可视区域高度,就可以展示置顶按钮
        if (e.target.scrollTop >= 0 && curHeight > viewHeight) {
          setDropDisplay(true);
        } else {
          setDropDisplay(false);
        }
                
        // 当可视区域底部到页面内容底部小于 200px 时触发页面自动滑动
        if (e.target.scrollTop >= 0 && curHeight <= viewHeight + 200) {
          setAutoDrop(true);
        }
      })
    }
  }, [chatContainerRef, chatList])
  
  // 流式输出内容时,触发页面滚动判断
  useEffect(() => {
    if (autoDrop) dropDown();
  }, [chatList])

  return (
     <>
         <div ref={chatContainerRef}>
            {chatList.map(item) => {
                // 渲染对话内容
            }}
         </div>
         {dropDisplay && <img src={toDown.src} onClick={dropDown} />}
     </>
  )
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容