ListView(React, JavaScript, HTML)

最近浏览百度新闻时发现百度新闻的列表随着新闻条目的扩大,庞大的DOM树严重拖累了滑动性能。于是乎便想找一个高性能列表,后来想到了Android的ListView和IOS的TableView轮循器机制。可惜遍寻各大网站也没有什么结果,只能自己实现一个。

基本原理:

轮循器的原理其实尤为简单,简而言之就是显示计算出当前列表所能显示的最大item数。也就是说即便在加载一万条数据时候DOM树上也只会留下当前所能显示的最大条目数的节点。

Handler(handler是用于操作item生成的工厂)

通过使用者注实现(抽象类,JS木有抽象所以请脑补抽象)iHandler。实现如下函数:

  • getView(item)=>JSX.Element

接受一个item,item为一个带有height和data的条目描述对象,height用于描述当前item高度,data为自定义数据。

该函数返回一个JSXView对象。该View将会被渲染在列表内。

  • getItem(index:number)=>{height:number,data:object}

接受当前条目索引,生产条目描述对象,最终将会用于view的生成。

  • getSize()=>number

返回条目总数目。


ListView

ListView将会根据handler产生列表,所必需接受的属性为 height 和 handler,其他属性为 tools 和 width。height是该view高度,handler为iHandler的实例。tools为需要向ListView获取的操作函数列表,width为宽度(如无则默认100%)。

下面用一个小Demo来演示ListView的使用。

import React from "react";
import Rx from "rxjs";
import { ListView, iHandler } from "./index";
import "./demo.css";
const viewSubject = new Rx.Subject().delay(200);
viewSubject.subscribe({
  next: ({ height, demo }) => {
    if (viewSubject.height == height) {
      console.log("view change");
      demo.setState({ height: height });
      tools.updataView();
    }
  }
});

const items = [];
for (let i = 0; i < 500; i += 1) {
  items[i] = i;
}

class Handler extends iHandler {
  getView(item) {
    let color = "white";
    let bg = "black";

    if (item.data % 2 == 1) color = "black";

    if (item.data % 2 == 1) bg = "white";

    return (
      <div
        className="item"
        style={{
          borderBottom: "1px solid black",
          background: color,
          width: "100%",
          height: "100%",
          color: bg
        }}
      >
        <img
          onClick={e => alert(item.data)}
          height={item.height}
          src="/images/24404591.jpeg"
        />
        {item.data}
      </div>
    );
  }
  getItem(index) {
    let h = 100;
    if (index != 0 && index % 3 == 0) {
      h = 120;
    }
    if (index != 0 && index % 5 == 0) {
      h = 160;
    }
    return { height: h, data: items[index] };
  }
  getSize() {
    return items.length;
  }
}
let height = 600;
const handler = new Handler();
const tools = {
  onScroll: null,
  updataView: null
};
export default class Demo extends React.Component {
  constructor(props) {
    super(props);
    window.onresize = e => {
      this.changeHeight();
    };
    this.state = {
      height: 200
    };
    this.changeHeight();
  }
  changeHeight() {
    let h = window.innerHeight - 200;
    h = h < 200 ? 200 : h;
    viewSubject.height = h;
    viewSubject.next({ height: h, demo: this });
  }
  render() {
    return (
      <div>
        <div style={{ float: "left" }}>
          <ListView
            isShowScroll={true}
            tools={tools}
            width={300}
            height={this.state.height}
            handler={handler}
          />
        </div>
        <div style={{ float: "left", marginLeft: "10px" }}>
          <div>U can change the browser's height to look at the result</div>
        </div>
      </div>
    );
  }
}


最后我通过直接生成div item与ListView做了比较。因为懒得设计view,所以item内只是简单填充数字,因此只能加大数量来测试。div直接生成直接在一万条项目的情况下卡死,而ListView秒读。

现在真实项目中已经有所使用,item条目最高时达到两千条依然没有任何性能问题,效果非常显著,而以前的普通item则直接卡死。

github地址:https://github.com/Saberteeth/react-redux-utils


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值