Make a react-window (2)

react-window2

Introduce:

as last time introduce react-window , I had separate the design structure try to understand how it work , and today I’m going use IntersectionObserverEntry to ****make simliar as react-window List component

List design

Div design:

https://miro.medium.com/max/1400/1*kzkpGbBG6ca3owkkqeHO4w.png

react-window paremeter is by px , here I want did some different is by hv , that will be more availability on the responsive

  • div1: we need set max height value when child element is over size will show scroll barmax-height: <parameter>by hvoverflow: auto
  • div2: here we need set virtual height for scroll barheight: itemCount * rowheight = total heightposition: relative
  • row div: per row we need give the top height to align and positionposition: absolutetop: by current indexclassName: tr

IntersectionObserverEntry:

we need pass two paremeter to IntersectionObserver

  • option :
const options = {root: document.getElementById('List'),rootMargin: `-${rowHeight}px 0px -${rowHeight}px 0px`,threshold: 0,};
  • callbackFunction :
useEffect(() => {
        let rowHeight = 0;
        const elementArrary2 = Array.prototype.slice.call(document.getElementsByClassName('tr')) as HTMLDivElement[];
        rowHeight = elementArrary2[0].clientHeight;

        const options = {
            root: document.getElementById('List'),
            rootMargin: `-${rowHeight}px 0px -${rowHeight}px 0px`,
            threshold: 0,
        };

        const onEnterView = (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => {
            for (let entry of entries) {
                if (entry.isIntersecting) {
                    const element = entry.target as HTMLDivElement;
                    const value = parseInt(element.style.top.split('hv')[0]);

                    if (value > height && value > currentIndex.current * rowheight) {
                        const reangeValue = value - height;
                        currentIndex.current = reangeValue / rowheight;
                        setMaxValue(value2 + currentIndex.current);

                      
                    } else if (0 !== currentIndex.current && value <= currentIndex.current * rowheight) {
                        currentIndex.current = value / rowheight;
                        currentIndex.current -= 1;
                        setMaxValue(value2 + currentIndex.current > height ? height : value2 + currentIndex.current);
                    }
                }
            }
        };
        const watcher = new IntersectionObserver(onEnterView, options);
        const elementArrary = Array.prototype.slice.call(document.getElementsByClassName('tr'));
        for (let image of elementArrary) {
            watcher.observe(image);
        }
    }, [maxValue]);

Dom

return (
        <div style={{ maxHeight: `${height}vh`, overflow: 'auto' }} id='List' className={classNames(` overflow-auto w-full relative`)}>
            <div
                className={`block  `}
                style={{
                    position: 'relative',
                    height: `${Rows?.length ? Rows?.length * rowheight : 2 * rowheight}vh`,
                }}
            >
                {Rows?.slice(currentIndex.current, maxValue).map((item, index) => (
                    <div
                        key={shortid.generate()}
                        className={`tr absolute`}
                        style={{
                            top: `${(index + currentIndex.current) * rowheight}vh`,
                            position: 'absolute',
                        }}
                    >
                        <Children index={index + currentIndex.current}></Children>
                    </div>
                ))}
            </div>
        </div>
    );

basically we are use Arrary slice function change currentIndex and maxValue when next element is be watched ,then will fall into the conditional and then them will be changed, and top height will be dynamic set up

https://miro.medium.com/max/1400/1*XnS6N_zqITW6gUArjlw7-g.png

Demo:

you can checkout more detail on this

https://codesandbox.io/s/nostalgic-sid-007ic8?from-embed

Github

you can checkout more detail on the github

****GitHub - outsider987/MyReact-windowThis project was bootstrapped with Create React App. In the project directory, you can run: Runs the app in the…** github.com

conclusion:

the reason I will dig more about the vitrual scroll tech is flexibility and customize requirement , as I use IntersectionObserverEntry as along that make me more familar with it ,but currently my Algorithm I think is not a perfect solution it’s still had optimization space , but I will working on it


留言

這個網誌中的熱門文章

Vue那些我踩過的坑(Vuex-TypeScript)

Vue(Vue3取代 Vuex?)

前端優化效能-1(lazy-img)