react实现列表向上自动滚动(二:hooks写法)

本文介绍了如何使用React、useState和useEffect创建一个可滚动的列表组件,通过监听滚动事件调整滚动位置,并在数据变化时保持流畅滚动。关键部分包括设置滚动距离和滚动定时器,以及处理鼠标hover和mouseout事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import React, { useState, useEffect, useRef } from 'react'

const MarqueeBox = (props) => {
    const [data, setData] = useState([]); //滚动的数据
    const [step, setStep] = useState(1) //滚动距离
    const [top, setTop] = useState(0) //滚动距离
    const [scrollTimer, setScrollTimer] = useState([])
    const [refObj, setRefObj] = useState(React.createRef())
    const saveCallBack = useRef()

    const callBack = () => {
        let { id } = props;
        let tbody = document.getElementById(id);
        if (!refObj.current) {
            clearInterval(scrollTimer)
        } else {
            if (refObj.current.scrollHeight - refObj.current.offsetHeight - 10 > 0) {
                let ss = top
                ss = ss + 1.5
                setTop(ss)
                setStep(top)
                tbody.scrollTo(0, top)
                if (ss >= refObj.current.scrollHeight - refObj.current.offsetHeight) {
                    setTop(0)
                    tbody.scrollTo(0, top)
                }
            } else {
                clearInterval(scrollTimer)
            }
        }
    }

    useEffect(() => {
        // 每次渲染后,保存新的回调到我们的 ref 里。
        saveCallBack.current = callBack;
        return () => { };

    });

    useEffect(() => {
        scrollTimer && clearInterval(scrollTimer)
        setData(props.data)
        initMove()
        return () => {
            scrollTimer && clearInterval(scrollTimer)
        }
    }, [props])

    /**
     * 行点击事件
     * @param {object} item 
     */
    function rowClick(item) {
        props.rowClick(item)
    }

    /**
     * 初始化滚动
     */
    function initMove() {
        let { id } = props;
        if (scrollTimer) {
            clearInterval(scrollTimer)
        }
        let tbody = document.getElementById(id);
        if (tbody) {
            const tick = () => {
                saveCallBack.current();
            };
            let tt = setInterval(tick, 90);
            setScrollTimer(tt)
        }
    }
    /**
     * 鼠标over事件
     */
    function onMouseOver() {
        scrollTimer && clearInterval(scrollTimer)
    }

    /**
     * 鼠标移出事件
     */
    function onMouseOut() {
        // scrollTop
        let { id } = props;
        let tbody = document.getElementById(id);
        setTop(tbody.scrollTop)
        initMove()
    }

    const boxStyle = {
        height: '100%',
        width: '100%',
        overflowY: "scroll"
    }
    return (
        <div className='marquee-box'
            id={props.id}
            style={boxStyle}
            ref={refObj}
            onMouseOver={onMouseOver}
            onMouseOut={onMouseOut}
            onTouchMove={onMouseOver}
            onTouchEnd={onMouseOut}
        >
            {
                data && data.map((item, index) => {
                    return (
                        <div key={index} className='list-item' onClick={() => rowClick(item)}>
                            <div className='list-item-td' title={item.originName}>{item.name1}</div>
                            <div className='list-item-td' title={item.finishName}>{item.name2}</div>
                            <div className='list-item-td' title={item.carId}>{item.id}</div>
                        </div>
                    )
                })
            }
        </div>
    )
}

export default MarqueeBox;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值