• React 长列表加载 实现虚拟列表


    React 长列表加载 实现虚拟列表

    效果


    实现思路

     定义一个container 高为一屏高
     定义一个listWrapper 高为所有列表元素的高度,来撑开容器
     定义一个itemWrapper 高为一屏高度,来跟随上、下拉操作进行位移,从而总是覆盖展示在当前屏
     
     滚动时关键值计算:
        一屏个数 limit: 1+(Math.ceil(containerHeight / itemHeight))  加1是预加载,多加载一项减少抖动
        start: 一屏的起始索引 Math.floor(scrollTop / itemHeight) 即滚动了几个元素
        end: 一屏的结束索引 start+limit
        transformY: 
                    下拉的位移。 滚动时,根据scrollTop计算出滚动过多少个元素,设置对应的start和end, 那么listWrapper的transformY值即为start*itemHeight(一屏起始索引*列表项高度)。下拉多少,就向下位移多少,让其一直展示在首屏
    

    具体实现


    ReactVirtualList

    import React, { useState, useMemo, memo } from 'react'
    import './ReactVirtualList.css'
    import { ListItem } from './ListItem';
    import { useCallback } from 'react';
    import { useRef } from 'react';
    
    const ReactVirtualList = (props) => {
        let { list, item: Item, contentWidth, contentHeight, itemHeight } = props
    
        const [start, setStart] = useState(0)
    
        const listDom = useRef()
    
        const limit = useMemo(() => {
            return 1 + Math.ceil(contentHeight / (itemHeight))
        }, [contentHeight, itemHeight]);
    
        const scrollHandler = useCallback(
            (e) => {
                const top = e.target.scrollTop
                const curStart = Math.floor(top / (itemHeight))
                curStart !== start && setStart(curStart)
            },
            [itemHeight, start]
        )
    
        const end = useMemo(() => {
            return Math.min(start + limit, list.length)
        }, [start, limit, list]);
    
        const renderList = useMemo(() => {
            return list
                .slice(start, end)
                .map((v, i) => (
                    <ListItem key={v.id} id={v.id} itemHeight={itemHeight} >
                        <Item text={v.v}></Item>
                    </ListItem>
                ))
        }, [start, end, list, itemHeight]);
    
        const transformY = useMemo(() => {
            return start * itemHeight + 'px'
        }, [start, itemHeight]);
    
        return <ul className='island-virtual-list' ref={listDom} onScroll={(e) => scrollHandler(e)} style={{  contentWidth + 'px', height: contentHeight + 'px' }}>
            <div className="listWrapper" style={{ height: itemHeight * list.length + 'px' }}>
                <div className="itemWrapper" style={{ height: contentHeight + 'px', transform: `translate3d(0, ${transformY}, 0)` }}>
                    {renderList}
                </div>
            </div>
        </ul>
    
    }
    
    export default memo(ReactVirtualList)
    

    样式

    .island-virtual-list {
        margin: auto;
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
        opacity: 0.8;
        overflow-y: auto;
        overflow-x: hidden;
        border: 1px solid #ccc;
    }
    
    .listWrapper {
        display: flex;
        flex-direction: column;
         100%;
    }
    
    .island-virtual-list-item {
        box-sizing: border-box;
         100%;
        font-size: 12px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-bottom: 1px solid black;
    }
    
    
    .itemWrapper {
        transform: translate3d(0, 0, 0);
    }
    

    使用

    import './App.css';
    import ReactVirtualList from './component/ReactVirtualList';
    
    const styleObj = {
      contentWidth: 800,
      contentHeight: 300,
      itemHeight: 50,
      itemWidth: 60
    }
    
    const Item = (props) => {
      return <div className='list-item'>{props.text}</div>
    }
    
    const list = Array(Math.floor((Math.random() + 1) * 10000)).fill().map((v, i, arr) => ({ id: i, v: i + '/' + arr.length + '   行' }))
    
    function App() {
      return <div className='app'>
        <ReactVirtualList {...styleObj} list={list} item={Item} ></ReactVirtualList>
      </div>
    }
    
    export default App;
    
  • 相关阅读:
    about springmvc intergation jquery with ajax &noajax version
    spring mvc book very good
    use spring config editor to configure xsi:schemaLocation
    install firefox9 on ubuntu lucid
    TCMalloc : ThreadCaching Malloc
    ubuntu amd64bit lts lucid lynx image download address
    一个词评价python 和rails
    virtualbox ubuntu下使用设置
    how to install chromium on ubuntu lucid
    Extjs4 MVC 示例
  • 原文地址:https://www.cnblogs.com/ltfxy/p/16086693.html
Copyright © 2020-2023  润新知