學習iOS開發(fā)的同學應該都知道UITableView,幾乎每個APP中都有它的存在,而且衍生出各種形態(tài);那么同樣,ListView就是在React Native中的tableView,而且更加簡單和靈活易用;讓我們一起搞定它。
一、前言
ListView組件是React Native中一個比較核心的組件,用途非常的廣; 該組件設計用來高效的展示垂直滾動的數(shù)據(jù)列表:
1.1 首先創(chuàng)建一個ListView.DataSource數(shù)據(jù)源,然后給它傳遞一個普通的數(shù)據(jù)數(shù)組;
1.2 使用數(shù)據(jù)源(data source)實例化一個ListView組件,定義一個renderRow回調(diào)函數(shù),這個函數(shù)會接受數(shù)組中的每個數(shù)據(jù)作為參數(shù),并返回一個可渲染的組件(該就是列表的每一行的item)。
二、ListView常用的屬性
ScrollView 相關(guān)屬性樣式全部繼承
dataSource ListViewDataSource 設置ListView的數(shù)據(jù)源
initialListSize number
設置ListView組件剛剛加載的時候渲染的列表行數(shù),用這個屬性確定首屏或者首頁加載的數(shù)量,而不是花大量的時間渲染加載很多頁面數(shù)據(jù),提高性能。
onChangeVisibleRows function (visibleRows,changedRows)=>void。
當可見的行發(fā)生變化的時候回調(diào)該方法。
onEndReachedThreshold number
當偏移量達到設置的臨界值調(diào)用onEndReached
onEndReached function
當所有的數(shù)據(jù)項行被渲染之后,并且列表往下進行滾動。一直滾動到距離底部onEndReachedThredshold設置的值進行回調(diào)該方法。原生的滾動事件進行傳遞(通過參數(shù)的形式)。
pageSize number 每一次事件的循環(huán)渲染的行數(shù)
removeClippedSubviews bool
該屬性用于提供大數(shù)據(jù)列表的滾動性能。該使用的時候需要給每一行(row)的布局添加over:'hidden'樣式。該屬性默認是開啟狀態(tài)。
renderFooter function 方法 ()=>renderable
在每次渲染過程中頭和尾總會重新進行渲染。如果發(fā)現(xiàn)該重新繪制的性能開銷比較大的時候,可以使用StaticContainer容器或者其他合適的組件。
renderHeader function 方法
在每一次渲染過程中Footer(尾)該會一直在列表的底部,header(頭)該會一直在列表的頭部,用法同上。
renderRow function (rowData,sectionID,rowID,highlightRow)=>renderable
該方法有四個參數(shù),其中分別為數(shù)據(jù)源中一條數(shù)據(jù),分組的ID,行的ID,以及標記是否是高亮選中的狀態(tài)信息。
renderScrollComponent function
方法 (props)=>renderable 該方法可以返回一個可以滾動的組件。默認該會返回一個ScrollView
renderSectionHeader function (sectionData,sectionID)=>renderable
如果設置了該方法,這樣會為每一個section渲染一個粘性的header視圖。該視圖粘性的效果是當剛剛被渲染開始的時候,該會處于對應的內(nèi)容的頂部,然后開始滑動的時候,該會跑到屏幕的頂端。直到滑動到下一個section的header(頭)視圖,然后被替代為止。
renderSeparator function (sectionID,rowID,adjacentRowHighlighted)=>renderable
如果設置該方法,會在被每一行的下面渲染一個組件作為分隔。除了每一個section分組的頭部視圖前面的最后一行。
scrollRenderAheadDistance number
進行設置當該行進入屏幕多少像素以內(nèi)之后就開始渲染該行
三、ListView的高階特性
ListView同樣支持一些高級特性,包括設置每一組的粘性的頭部(類似于iPhone)、支持設置列表的header以及footer視圖、當數(shù)據(jù)列表滑動到最底部的時候支持onEndReached方法回調(diào)、設備屏幕列表可見的視圖數(shù)據(jù)發(fā)生變化的時候回調(diào)onChangeVisibleRows以及一些性能方面的優(yōu)化特性。
ListView設計的時候,當需要動態(tài)加載非常大的數(shù)據(jù)的時候,下面有一些方法性能優(yōu)化的方法可以讓我們的ListView滾動的時候更加平滑:
(1)只更新渲染數(shù)據(jù)變化的那一行 ,rowHasChanged方法會告訴ListView組件是否需要重新渲染當前那一行。
(2)選擇渲染的頻率,默認情況下面每一個event-loop(事件循環(huán))只會渲染一行(可以同pageSize自定義屬性設置)。這樣可以把大的工作量進行分隔,提供整體渲染的性能。
四、綜合大演練
4.1 最簡單的ListView
核心代碼:
運行效果截圖:
4.2 帶有組頭的汽車品牌展示
核心代碼:
運行結(jié)果:
項目技術(shù)點分析:
在React Native中,ScrollView組件可以使用 stickyHeaderIndices 輕松實現(xiàn) sticky 效果;而使用ListView組件時,使用 stickyHeaderIndices 則不生效。
如何實現(xiàn)滾動時每個section header會吸頂?
在ListView中要實現(xiàn) sticky ,需要使用 cloneWithRowsAndSections 方法,將 dataBlob(object), sectionIDs (array), rowIDs (array) 三個值傳進去。
dataBlob
dataBlob 包含ListView所需的所有數(shù)據(jù)(section header 和 rows),在ListView渲染數(shù)據(jù)時,使用getSectionData 和 getRowData 來渲染每一行數(shù)據(jù)。 dataBlob 的 key 值包含 sectionID + rowId
sectionIDs
sectionIDs 用于標識每組section。
rowIDs
rowIDs 用于描述每個 section 里的每行數(shù)據(jù)的位置及是否需要渲染。在ListView渲染時,會先遍歷 rowIDs 獲取到對應的 dataBlob 數(shù)據(jù)。
模擬對應的數(shù)據(jù)結(jié)構(gòu)
在 DataSource 中,設置ListView獲取row和section的方法
最后
- 刷新狀態(tài),將數(shù)據(jù)傳入到listView中:
this.setState({
dataSource:this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs)
});
- 設置listView的相關(guān)屬性:
<ListView
dataSource = {this.state.dataSource}
renderRow = {this.renderRow}
renderSectionHeader = {this.renderSectionHeader}
/>
4.3 用ListView實現(xiàn)九宮格布局
相關(guān)技術(shù)點:
通常情況下,我們對ListView的操作是縱向的,如果是橫向的,則需要設置ListView的contentContainerStyle屬性,添加flexDirection:‘row’讓多個ListView在同一行顯示,而且通過flexWrap:'wrap'進行換行。
核心代碼:
運行效果: