此文章中,包括簡單的布局,九宮格布局和頭視圖的使用小demo
前言
在iOS開發中,用的最多的一個控件就是TableView,ListView和TableView實現的效果一下,是React Native中的核心組件,高效的用于顯示一個可以垂直滾動變化的數據列表。
TableView的工作原理是:先加載UI,有數據源之后再刷新界面。
ListView的工作原理是:想創建一個ListView.DataSource數據源,然后給他傳遞一個普通的的數據組,在使用數據源來實例化一個ListView組件。使用renderRow回調函數,接受數組中的每個數組作為參數,返回一個可渲染的組件。
一、ListView常用屬性
ListView ?繼承ScrollerView相關的樣式屬性
DataSource? ?數據屬性
initialListSize ?number?
?控制組件剛掛載的時候渲染多少行數據,用來確保首屏顯示合適數量的數據,而不是花費太多幀逐步顯示出來。
onEndReachedThreshold ?number?
?設置什么時候偏移量達到設置的臨界值調用onEndReached
pageSize ?number ?
每幀渲染的行數
removeClippedSubviews? bool? ?
該屬性用于提供大數據列表的滾動性能。該使用的時候需要給每一行(row)的布局添加over:'hidden'樣式。該屬性默認是開啟狀態。
scrollRenderAheadDistance ?number?
當一行接近屏幕范圍多少像素之內的時候,開始渲染這一行。
IOS ? stickyHeaderIndices[number]
一個子視圖下標的數組,用于決定哪些成員會在滾動之后固定在屏幕頂端。?
function屬性
onChangeVisibleRows? (visibleRows,changedRows)=>void??
?當可見的行發生變化的時候回調該方法。?
onEndReached??
當所有的數據都已經渲染過,并且列表被滾動到距離最底部不足onEndReachedThreshold個像素的距離時調用原生的滾動事件會被作為參數傳遞。
注意:當第一次渲染時,如果數據不足一屏(比如初始值是空的),這個事件也會被觸發。
renderFooter? ()=>renderable??
在每次渲染過程中頭和尾總會重新進行渲染。如果發現該重新繪制的性能開銷比較大的時候,可以使用StaticContainer容器或者其他合適的組件。
renderHeader? 在每一次渲染過程中Footer(尾)該會一直在列表的底部,header(頭)該會一直在列表的頭部,用法同上。
renderRow ??(rowData,sectionID,rowID,highlightRow)=>renderable
該方法有四個參數,其中分別為數據源中一條數據,分組的ID,行的ID,以及標記是否是高亮選中的狀態信息。
renderScrollComponent ? (props)=>renderable??
該方法可以返回一個可以滾動的組件。默認該會返回一個ScrollView
renderSectionHeader??(sectionData,sectionID)=>renderable
如果設置了該方法,這樣會為每一個section渲染一個粘性的header視圖。該視圖粘性的效果是當剛剛被渲染開始的時候,該會處于對應的內容的頂部,然后開始滑動的時候,該會跑到屏幕的頂端。直到滑動到下一個section的header(頭)視圖,然后被替代為止。
renderSeparator ?(sectionID,rowID,adjacentRowHighlighted)=>renderable
如果設置該方法,會在被每一行的下面渲染一個組件作為分隔。除了每一個section分組的頭部視圖前面的最后一行。
方法
導出一些用于性能分析的數據。
scrollTo
滾動到指定的X,Y偏移處,可以指定是否加上過渡動畫。
二、ListView高級特性
2.1給每段/組數據天天以后帶有粘性的頭部。
2.2在列表頭部和尾部增加單獨的內容,在到達列表尾部的時候調用函數(onEndReached),還有在視野可見的數據變化時調用回調函數(onChangeVisibleRows)。
2.3在性能方面優化
只更新變化的行 - 提供給數據源的rowHasChanged函數可以告訴ListView中它是否需要重繪一行數據(即:數據是否發生了變化)參見ListViewDataSource
限制頻率的行渲染-默認情況下,每次消息循環只有一行會被渲染(用可以pageSize屬性配置)這把較大的工作分散成小的碎片,以降低因為渲染而導致丟幀的可能性。
三、ListView常用Demo
3.1簡單的電商demo
3.1.1listView的使用步驟:
代碼截圖:
運行效果:
這種比較簡單,只要到時候改變返回的row中的View的樣式即可
3.2九宮格demo
使用ListView實現九宮格的原理就是,一個listView,將cell通過flex布局實現,主軸方向的改變,然后設置,每個cell的布局得到。
注意:在這個過程中,實現row主軸的改變后,實現多行顯示總是不行,原因是removeClippedSubviews={false}的默認狀態是ture是隱藏的。
3.2.1 代碼截圖:
運行截圖:
3.3分組帶有頭視圖的demo?
DataSource 的方法解析及技術分析
1.數組的提取和更新方法
clone方法會自動提取新數據并進行逐行對比(使用rowHasChanged方法中的策略),這樣ListView就知道哪些行需要重新渲染了。
?cloneWithRows(dataBlob(原始數據), rowIdentities(二維數組))
cloneWithRowsAndSections(dataBlob(原始數據), sectionIdentities(數組,包含了section標識符), rowIdentities(數組))
section標題和行數據提供自定義的提取方法和hasChanged比對方法。如果不提供,則會使用默認的defaultGetRowData和defaultGetSectionHeaderData方法來提取行數據和section標題。
默認的提取函數處理一下的數據類型
{ sectionID_1: { rowID_1: rowData1, ... }, ... } ? ? =>>> ? key:{}
{ sectionID_1: [ rowData1, rowData2, ... ], ... }? ? =>>> ? key:[]
[ [ rowData1, rowData2, ... ], ... ] ? ? ? ? ? ? ? ? ?= >>>> [[],[]....]
通過構造函數提取數組的方法一共有四種:
(1).getRowData(sectionIndex, rowIndex)? ? 返回渲染行數所需的數據(指定如何從原始dataBlob中提取數據)。
(2).getSectionHeaderData(dataBlob, sectionID); 獲取section標題數據。
(3)rowHasChanged(prevRowData, nextRowData); ?通過對比創建數組
(4). sectionHeaderHasChanged(prevSectionData, nextSectionData); ?通過對比創建
2.其他方法
getRowCount() ?獲取行數
getRowAndSectionCount() ? 獲取原始數據的分組個數
rowShouldUpdate(sectionIndex, rowIndex) ??返回值表明某行數據是否已變更,需要重新渲染。
getRowData(sectionIndex, rowIndex) ??返回渲染行所需的數據(指定如何從原始dataBlob中提取數據)。
getSectionIDForFlatIndex(index) ? ?給定索引值,求其對應sectionID。如果查找不到則返回null。
getSectionLengths() ??返回一個數組,包含每個section的行數量。
sectionHeaderShouldUpdate(sectionIndex) ??返回值用于說明section標題是否需要重新渲染。
看到上邊的大家可能還是蒙蒙的,簡單的說就說:
DataBlob就是原始數據就是一個大的字典{
sectionID1:{},或者[]
}
sectionIDs = ['sectionID1',sectionID2',sectionID3'.......] 每組的標題
rowIDS = [[row1,row2],[row1,row2],[row1,row2],[row1,row2].....] ?每組的數據
第一步需要在datasource中,設置ListView獲取row和section方法
第二步因為需要對數據進行循環拆分,組合成dataBlob需要的數據樣式屬于耗時操作,放到componentDidMount方法中,完成操作后刷新狀態,將數據傳到listView的render()方法中。
第三步,返回相關函數,設置屬性樣式布局
代碼截圖
運行結果:
完整demo請https://github.com/nanaLxs/ListView-demo下載。如果感覺可以請star。在這里謝謝啦!!