rax学习(八):实现微信消息长列表(LongList)之性能优

2020-08-23  本文已影响0人  _志铭

仓库地址:rax-longlist

介绍一下

前一节我们可以看到,数据量一上来就出现了很多问题。本节我们就来讲讲这些bug的解决办法。首先我们要知道为什么会出现这个问题,我们的长列表在大量数据(上千条,这个量级并不多)的情况下会出现拖动卡顿甚至拖不动,控制台也报错了。我们可以分析一下出现问题的原因,控制台报的错误如下

image

需求

解决方案

代码展示

image
import {createElement, createRef, useEffect, useState} from 'rax';
import View from 'rax-view';
import ScrollView from 'rax-scrollview';
import './index.css';
/**
 * 虚拟列表例子
 */
const scrollRef = createRef();

const bottomRef = createRef();
const topRef = createRef();

const firstRef = createRef();
const secondRef = createRef();
const thirdRef = createRef();

let page = 1;
let prevDis = 2;
let currDis = 0;
export default () => {
  let [page1, setPage1] = useState(1);
  let [page2, setPage2] = useState(2);
  let [page3, setPage3] = useState(3);
  function handleScroll() {
    scrollRef.current._nativeNode.addEventListener('scroll', (e) => {
      let y = bottomRef.current.getBoundingClientRect().bottom;
      // 最底部item的底部到屏幕最上方的距离比上屏幕的距离,我们已知底部导航的高度占屏幕高度的10%
      currDis = y / document.documentElement.clientHeight;
      // 计算比率,检测是否到底了
      let distance = 0.91;
      // 向上滑动
      if (currDis < distance && currDis < prevDis) {
        // console.log('向上滑动', page);
        bottomRef.current.style.bottom = `-${100 * page}vh`;
        if (page % 3 === 1) {
          thirdRef.current.style.top = `${100 * page + 100}vh`;
          setPage3(page + 2);
        } else if (page % 3 === 2) {
          firstRef.current.style.top = `${100 * page + 100}vh`;
          setPage1(page + 2);
        } else if (page % 3 === 0) {
          secondRef.current.style.top = `${100 * page + 100}vh`;
          setPage2(page + 2);
        }
        page++;
      // 向下滑动
      } else if (currDis > distance && currDis > prevDis) {
        // console.log('向下滑动', page);
        bottomRef.current.style.bottom = `-${100 * page}vh`;
        if (page % 3 === 1) {
          thirdRef.current.style.top = `${100 * page - 200}vh`;
          setPage3(page - 1 );
        } else if (page % 3 === 2) {
          firstRef.current.style.top = `${100 * page - 200}vh`;
          setPage1(page - 1);
        } else if (page % 3 === 0) {
          secondRef.current.style.top = `${100 * page - 200}vh`;
          setPage2(page - 1);
        }
        page--;
      }
    });
  }
  useEffect(() => {
    handleScroll();
  }, [page]);
  return <ScrollView className="list-wrapper" ref={scrollRef}>
    <View className="page-wrap">
      <View className="top" ref={topRef}>到顶了~</View>
      <View className="first page" ref={firstRef} >{page1}</View>
      <View className="second page" ref={secondRef} >{page2}</View>
      <View className="third page" ref={thirdRef} >{page3}</View>
      <View className="bottom" ref={bottomRef}>到底了~</View>
    </View>
  </ScrollView>;
};

效果展示

我们通过浏览器滚动帧率的工具来查看效果,操作如下:

image image

通过上面设置我们可以轻松的查看到滚动帧率的变化,帧率越大代表动画越流畅。使用virturelist的话,滚动到3000条左右的时候,每一页能存放10条,也就是数字300左右的时候,帧率值依旧非常大

virturelist

我们再来看看RecyclerList 3000条左右数据的时候的表现

recyclerlist

最后我们看看,不做任何处理的时候,使用ScrollView 3000条数据时候的表现

scrollview

以上对比可能有些偏差,后续有时间会改进的。

参考

上一篇下一篇

猜你喜欢

热点阅读