列表視圖——為變化的數據列表的垂直滾動的高效顯示而設計的一個核心組件。最小的 API 是創(chuàng)建一個ListView.DataSource
,用一個簡單的數組數據的 blob 填充,并用那個數據源實例化一個 ListView
組件和一個renderRow
回調,它會從數組數據中帶走一個 blob 并返回一個可渲染的組件。
最小的例子:
getInitialState: function() { var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); return { dataSource: ds.cloneWithRows(['row 1', 'row 2']), }; },render: function() { return ( <ListView dataSource={this.state.dataSource} renderRow={(rowData) => <Text>{rowData}</Text>} /> ); },
列表視圖還支持更高級的功能,包括帶有 sticky 頁眉的部分,頁眉和頁腳的支持,回調到可用數據的最后(onEndReached
)和設備窗口變化中可見的行集(onChangeVisibleRows),以及一些性能優(yōu)化。
當動態(tài)加載一些可能非常大(或概念上無限大的)數據集時,為了讓列表視圖滾送的順暢,有一些性能操作設計:
只有重新呈現改變行——提供給數據源的 hasRowChanged 函數告訴列表視圖是否需要重新呈現一行,因為源數據發(fā)生了變化——更多細節(jié)請看 ListViewDataSource。
行限速呈現——默認情況下,每次事件循環(huán)時,只顯示一行 (可用pageSize
道具定制)。這將工作分解為小塊,在呈現行時,減少框架下降的機會。
ScrollView props...
dataSource 列表視圖數據源
initialListSize 數字型
多少行呈現在初始組件裝置中。使用這個來實現,這樣第一個屏幕需要的數據就會一次出現,而不是在多個框架的過程中出現。
onChangeVisibleRows 函數型
(visibleRows, changedRows) => void
當可見的行集改變時調用。visibleRows
為所有可見的行映射 { sectionID: { rowID: true }}
,changedRows
為已經改變了它們可見性的行映射 { sectionID: { rowID: true | false }}
,true 表明行可見,而 false 表明行已經從視圖中被刪除了。
onEndReached 函數型
當所有行已經呈現并且列表被滾動到了 onEndReachedThreshold 的底部時被調用。提供了 native 滾動事件。
onEndReachedThreshold 數字型
onEndReached 像素的閾值。
pageSize 數字型
每次事件循環(huán)顯示的行的數量。
removeClippedSubviews 布爾型
為提高大型列表滾動性能的實驗性能優(yōu)化,與溢出一起使用:“隱藏”在行容器中。使用時自己承擔風險。
renderFooter 函數型
() => renderable
頁眉和頁腳在每個呈現過程中都會出現(如果提供了這些道具)。如果重新呈現它們耗費很大,那就把它們包在 StaticContainer 或其他適當的機制中。在每一個呈現過程中,頁腳始終是在列表的底部,頁眉始終在列表的頂部。
renderHeader 函數型
renderRow 函數型
(rowData, sectionID, rowID) => renderable 需要從數據源和它的 id 取走一個數據條目,并返回一個可渲染的作為行呈現的組件。默認的情況下,數據正是被放入了數據源的東西,但也可以提供自定義的提取器。
renderSectionHeader 函數型
(sectionData, sectionID) => renderable
如果提供了該函數,那么本節(jié)的 sticky 頁眉就會呈現。Sticky 行為意味著它將帶著本節(jié)頂部的內容滾動,直到它到達屏幕的頂端,此時它會停在屏幕頂部,直到被下一節(jié)的頁眉推掉。
scrollRenderAheadDistance 數字型
在它們以像素的形式出現在屏幕上之前,要多早就開始呈現行。
'use strict';var React = require('react-native');var { Image, ListView, TouchableHighlight, StyleSheet, Text, View, } = React;var UIExplorerPage = require('./UIExplorerPage');var ListViewSimpleExample = React.createClass({ statics: { title: '<ListView> - Simple', description: 'Performant, scrollable list of data.' }, getInitialState: function() { var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); return { dataSource: ds.cloneWithRows(this._genRows({})), }; }, _pressData: ({}: {[key: number]: boolean}), componentWillMount: function() { this._pressData = {}; }, render: function() { return ( <UIExplorerPage title={this.props.navigator ? null : '<ListView> - Simple'} noSpacer={true} noScroll={true}> <ListView dataSource={this.state.dataSource} renderRow={this._renderRow} /> </UIExplorerPage> ); }, _renderRow: function(rowData: string, sectionID: number, rowID: number) { var rowHash = Math.abs(hashCode(rowData)); var imgSource = { uri: THUMB_URLS[rowHash % THUMB_URLS.length], }; return ( <TouchableHighlight onPress={() => this._pressRow(rowID)}> <View> <View style={styles.row}> <Image style={styles.thumb} source={imgSource} /> <Text style={styles.text}> {rowData + ' - ' + LOREM_IPSUM.substr(0, rowHash % 301 + 10)} </Text> </View> <View style={styles.separator} /> </View> </TouchableHighlight> ); }, _genRows: function(pressData: {[key: number]: boolean}): Array<string> { var dataBlob = []; for (var ii = 0; ii < 100; ii++) { var pressedText = pressData[ii] ? ' (pressed)' : ''; dataBlob.push('Row ' + ii + pressedText); } return dataBlob; }, _pressRow: function(rowID: number) { this._pressData[rowID] = !this._pressData[rowID]; this.setState({dataSource: this.state.dataSource.cloneWithRows( this._genRows(this._pressData) )}); }, });var THUMB_URLS = ['https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851549_767334479959628_274486868_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851579_767334503292959_179092627_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851589_767334513292958_1747022277_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851563_767334559959620_1193692107_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851593_767334566626286_1953955109_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851591_767334523292957_797560749_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851567_767334529959623_843148472_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851548_767334489959627_794462220_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851575_767334539959622_441598241_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-ash3/t39.1997/p128x128/851573_767334549959621_534583464_n.png', 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851583_767334573292952_1519550680_n.png'];var LOREM_IPSUM = 'Lorem ipsum dolor sit amet, ius ad pertinax oportere accommodare, an vix civibus corrumpit referrentur. Te nam case ludus inciderint, te mea facilisi adipiscing. Sea id integre luptatum. In tota sale consequuntur nec. Erat ocurreret mei ei. Eu paulo sapientem vulputate est, vel an accusam intellegam interesset. Nam eu stet pericula reprimique, ea vim illud modus, putant invidunt reprehendunt ne qui.';/* eslint no-bitwise: 0 */var hashCode = function(str) { var hash = 15; for (var ii = str.length - 1; ii >= 0; ii--) { hash = ((hash << 5) - hash) + str.charCodeAt(ii); } return hash; };var styles = StyleSheet.create({ row: { flexDirection: 'row', justifyContent: 'center', padding: 10, backgroundColor: '#F6F6F6', }, separator: { height: 1, backgroundColor: '#CCCCCC', }, thumb: { width: 64, height: 64, }, text: { flex: 1, }, });module.exports = ListViewSimpleExample;
更多建議: