1. 程式人生 > >react native 索引列表、展示大量資料的索引列表、磁吸索引列表、快速載入大量資料的列表

react native 索引列表、展示大量資料的索引列表、磁吸索引列表、快速載入大量資料的列表

近期,在完成一個含有索引列表功能的專案。效果如圖所示:

首先,我用的是react native 所提供的 ListView  這個元件(由於這個元件已經過期,而且此列表為分組列表,所以建議大家使用react native 官網所提供的  SectionList  元件,後面會有demo來講解如何使用),然後計算每個組的高度,然後存起來,在點選索引的時候,用 元件所提供的scrollTo 方法來進行滑動調相應的位置。我的具體實現為:

(1)用ListView元件,將列表展示出來

<ListView ref={listView => this._listView = listView}      
          contentContainerStyle={styles.contentContainer}
          dataSource={this.state.dataSource}
          renderRow={this._renderListRow.bind(this)}
          renderSectionHeader={this._renderListSectionHeader.bind(this)}
          enableEmptySections={true}
          initialListSize={500}/>
(2) /*分組的組名*/
    _renderListSectionHeader(sectionData, sectionID) {
        組名的渲染,具體程式碼,在後面看後面提供的具體demo
    }
(3)/*主體資料列表*/
    _renderListRow(cityJson, rowId) {
    每一行資料的渲染,這裡分為了關鍵字為字母和非字母兩種渲染格式。具體程式碼,看後面提供的具體demo
}
(4){/*索引*/}
<View style={{
    position: 'absolute',
    height: height,
    top: this.state.letterMarginTop,
    bottom: 0,
    right: this.state.letterMarginRight,
    backgroundColor: 'transparent',
    justifyContent: 'flex-start',
    alignItems: 'flex-end'
    // alignItems: 'center',
    //justifyContent: 'center'
}}>
    索引採用絕對定位的方式,將索引定位到右側。具體程式碼,看後面提供的具體demo
</View>

最後實現的效果圖,如下:

 具體的demo地址: https://github.com/LQ0611/IndexList.git

如果想看效果,請將本包引入你的專案中,並呼叫包中  test-MainPage  頁面;如果想實際使用,請看包中 readme 檔案。

在實際使用中,由於出入的資料在幾百個,資料量過大,而且由於要計算各個組的高度,所以這些資料必須第一次時就要全部渲染,所以這個元件在進入的時候,非常慢。因此,為了改善進入的體驗,而有了改進版,如下介紹。

(1)將資料展示出來

<LargeList

    style={{ width:width,height:height-70,}}  // 樣式
    ref={ref => (this._listView = ref)}      //後面在滾動時,用它來做標識,明確操作的是哪一個
    reloadData={this.state.contacts}         //傳入的資料
    numberOfSections={()=>this.state.contacts.length}    //本資料中有多少個組
    numberOfRowsInSection={section => this.state.contacts[section].info.length}    //某一組中,有多少條資料
    heightForCell={()=>this.state.heightForCell}            //渲染每一條資料時,所佔的高是多少
    heightForSection={()=>this.state.heightForSection}      //渲染時,每個組名所佔的高是多少
    renderSection={this.renderSection.bind(this)}           //組名的渲染方法
    renderCell={this._renderItem.bind(this)}                //組內資料的渲染方法

    renderFooter={this.renderFooter.bind(this)}             //在滑動到列表底部時,在列表底部所顯示的提示內容
   />

(2)滾動的計算與實現

首先,將我們資料中的header取出,並通過toUpperCase方法,轉換成大寫

然後,將取出的組名存放到一個數組中備用

在然後,根據統計出的每個組有多少條資料 * 設定好的資料的高度  +  多少個組* 每個組的高度,將計算得到的結果,儲存進資料,當點選某個索引是,就能直接得到要滾動 的距離

this.state.contacts.map(contacts => {
    let key = contacts.header.toUpperCase();

    if (dataBlob[key]) {
        let subList = dataBlob[key];
        subList.push(contacts);
    } else {
        let subList = [];
        subList.push(contacts);
        dataBlob[key] = subList;
    }
});

let sectionIDs = Object.keys(dataBlob);

/*計算高度*/
let rowIDs = sectionIDs.map((sectionID,i) => {
    let thisRow = [];
    let count = this.state.contacts[i].info.length;
    console.log("count:",count);
    for (let ii = 0; ii < count; ii++) {
        thisRow.push(ii);
    }

    let eachheight = this.state.heightForSection + this.state.heightForCell * thisRow.length;
    //if (sectionID === key_hot || sectionID === key_now || sectionID === key_last_visit) {

    totalheight.push(eachheight);

    return thisRow;
});

滾動事件:

_scrollTo(index, letter) {
    this.refs.toast.close();
    let position = 0;
    for (let i = 0; i < index; i++) {
        position += totalheight[i]
    }

    console.log("position",position)
    this._listView.scrollTo({x:0,y:position+5}) ;  //滾動方法
    this.refs.toast.show(letter, DURATION.LENGTH_SHORT);  //在點選某個索引時 ,螢幕上回短暫的顯示此索引的字母
}

(3)索引的實現

{/*索引*/}
<ScrollView style={{
    position: 'absolute',
    height: this.state.letterHeight,
    top: this.state.letterMarginTop,
    bottom: 0,
    right: this.state.letterMarginRight,
    backgroundColor: 'transparent',

    // alignItems: 'center',
    //justifyContent: 'center'
}}>
    索引也是採用絕對定位到右邊。詳情請看後面的具體的demo
</ScrollView>

(4)組名的展示方法

/*組名*/
    renderSection(section){
    具體的展示程式碼請看下面的demo
}

(5)組內資料的展示

/*主體資料展示*/
    _renderItem (section: number, row: number){
 具體的展示程式碼請看下面的demo
}

具體的demo地址:https://github.com/LQ0611/IndexList-v2.git

效果圖: