ListView(React, JavaScript, HTML)

来源:互联网 发布:单例模式 java代码 编辑:程序博客网 时间:2024/06/05 00:36

最近浏览百度新闻时发现百度新闻的列表随着新闻条目的扩大,庞大的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


原创粉丝点击