ListView 高效数据列表 >=v1.0.0
最基本的使用方式就是创建一个ListView.DataSource数据源,然后给它传递一个普通的数据数组,再使用数据源来实例化一个ListView组件,并且定义它的renderRow回调函数,这个函数会接受数组中的每个数据作为参数,返回一个可渲染的组件(作为listview的每一行)。
注:该版本暂时不支持scrollTo。
dataSource { ListViewDataSource }
源数据。
initialListSize { number }
指定在组件刚挂载的时候渲染多少行数据。用这个属性来确保首屏显示合适数量的数据,而不是花费太多帧逐步显示出来。
onChangeVisibleRows { function }
(visibleRows, changedRows) => void
当可见的行的集合变化的时候调用此回调函数。visibleRows 以 { sectionID: { rowID: true }}的格式包含了所有可见行,而changedRows 以{ sectionID: { rowID: true | false }}的格式包含了所有刚刚改变了可见性的行,其中如果值为true表示一个行变得可见,而为false表示行刚刚离开可视区域而变得不可见。
方法参数:
参数名 | 类型 | 描述 | 版本 |
---|---|---|---|
visibleRows | object | 当前可见行 | |
changedRows | object | 可见状态改变的行 |
onEndReached { function }
当所有的数据都已经渲染过,并且列表被滚动到距离最底部不足onEndReachedThreshold个像素的距离时调用。原生的滚动事件会被作为参数传递。
onEndReachedThreshold { number }
调用onEndReached之前的临界值,单位是像素。
pageSize { number }
每次事件循环(每帧)渲染的行数。
renderFooter { function }
() => renderable
页头与页脚会在每次渲染过程中都重新渲染(如果提供了这些属性)。如果它们重绘的性能开销很大,可以考虑使用renderStaticHeader/renderStaticFooter。页脚会永远在列表的最底部,而页头会在最顶部。
返回值: renderable 页头组件
renderHeader { function }
() => renderable
同renderFooter,渲染页尾组件。
返回值: renderable 页尾组件
renderStaticFooter { function }
() => renderable
只渲染一次的头部组件。
返回值: renderable 页头组件
renderStaticHeader { function }
() => renderable
只渲染一次的尾部组件。
返回值: renderable 页尾组件
renderRow { function }
(rowData, sectionID, rowID, highlightRow) => renderable
从数据源(Data source)中接受一条数据,以及它和它所在section的ID。返回一个可渲染的组件来为这行数据进行渲染。默认情况下参数中的数据就是放进数据源中的数据本身,不过也可以提供一些转换器。
方法参数:
参数名 | 类型 | 描述 | 版本 |
---|---|---|---|
rowData | React.PropTypes.any | 数据源中的数据 | |
sectionID | string | 所处section名 | |
rowID | number | 所处section中的index | |
highlightRow | function | 通过调用该函数可通知ListView高亮该行 |
返回值: renderable 每行渲染组件
renderScrollComponent { function }
(props) => renderable
指定一个函数,在其中返回一个可以滚动的组件。ListView将会在该组件内部进行渲染。默认情况下会返回一个包含指定属性的ScrollView。
方法参数:
参数名 | 类型 | 描述 | 版本 |
---|---|---|---|
可滚动组件的属性 | object |
返回值: renderable 可滚动组件
renderSeparator { function }
(sectionID, rowID, adjacentRowHighlighted) => renderable
如果提供了此属性,一个可渲染的组件会被渲染在每一行下面,除了小节标题的前面的最后一行。
方法参数:
参数名 | 类型 | 描述 | 版本 |
---|---|---|---|
sectionID | string | 所处section名 | |
rowID | number | 所处section中的index | |
adjacentRowHighlighted | bool | 邻近的行是否被高亮 |
返回值: renderable 分隔组件
scrollRenderAheadDistance { number }
当一个行接近屏幕范围多少像素之内的时候,就开始渲染这一行。
useOriginScrollView { bool }
如果提供了此属性, 会使用原生ScrollView,配置了renderScrollComponent时不生效。
scrollEventThrottle { bool }
触发onScroll最小间隔毫秒数,默认值为50。
getScrollResponder
获取ScrollView,当使用原生ScrollView时(useOriginScrollView属性为true)返回滚动响应器。
返回值: scrollResponder ScrollView,当使用原生ScrollView时返回滚动响应器
startRefreshing
同ScrollView,当前组件有refreshControl属性,并且没有正在下拉刷新,则强制触发下拉刷新,变成正在刷新的状态。
stopRefreshing
同ScrollView,当前组件有refreshControl属性,并且正在下拉刷新,则停止下拉刷新的状态。
startLoading
同ScrollView,当前组件有loadControl属性,并且没有正在加载,则强制触发加载更多,变成正在加载更多的状态。
stopLoading
同ScrollView,当前组件有loadControl属性,并且正在加载,则停止加载更多的状态。
scrollToTop
返回顶部,可通过{animated: true}开启动画。可以参考这个例子。
import React, {
Component,
StyleSheet,
View,
Text,
TouchableOpacity,
Image,
ListView,
RefreshControl,
LoadControl,
} from 'qunar-react-native'
// listview example
class ListViewExample extends Component {
constructor(props){
super(props)
this.componentTimeouts = []
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
})
let rows = []
for(let i = 0; i < 30; i++){
rows.push(i)
}
this.state = {
rows: rows,
dataSource: ds.cloneWithRows(rows),
}
}
// 下拉刷新
onRefresh() {
this.componentTimeouts.push(setTimeout(() => {
this.pushRows(10)
this.refs.listview.stopRefreshing()
}, 2000))
}
// 上拉加载
onLoad() {
this.componentTimeouts.push(setTimeout(() => {
this.pushRows(20)
this.refs.listview.stopLoading()
}, 2000))
}
pushRows(number) {
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
})
let rows = this.state.rows,
len = rows.length
for(let i = 0; i < number; i++){
rows.push(len + i)
}
this.setState({
rows: rows,
dataSource: ds.cloneWithRows(rows),
})
}
render() {
return (
<View style={styles.container}>
<ListView
ref="listview"
dataSource={this.state.dataSource}
renderRow={(rowData) => <ListViewExampleRow title={rowData}/>}
refreshControl={<RefreshControl onRefresh={this.onRefresh.bind(this)} />}
loadControl={
<LoadControl onLoad={() => this.onLoad()}
onPress={() => {
this.refs.listview.startLoading()
this.onLoad()
}}
/>
}
/>
</View>
)
}
componentWillUnmount() {
for(var timeout of this.componentTimeouts){
clearTimeout(timeout)
}
}
}
// example row content
class ListViewExampleRow extends Component {
constructor(props){
super(props)
}
render() {
const {title} = this.props
const url = 'http://placeholdit.imgix.net/~text?txtsize=33&bg=666&txtclr=fff&txt=' + title + '&w=100&h=110',
randomText = Number(title) % 100
return (
<View style={styles.row}>
<Image
style={[styles.rowImg]}
source={{uri: 'http://placeholdit.imgix.net/~text?txtsize=33&bg=666&txtclr=fff&txt=' + title + '&w=100&h=110'}}
/>
<View style={[styles.rowContent]}>
<View style={{flexDirection: 'row'}}>
<Text style={styles.titleText}>{title}</Text>
</View>
<View>
<Text style={{color: '#25a4bb'}}>{randomText}分 / {randomText}条评论</Text>
<Text style={[styles.alignRight, {color: 'orange'}]}>{randomText}起</Text>
</View>
<View>
<View style={[styles.labelWrap]}>
<Text style={[styles.labelText]}>label{randomText}</Text>
<Text style={[styles.labelText]}>label{randomText}</Text>
<Text style={[styles.labelText]}>label{randomText}</Text>
</View>
<Text style={[styles.alignRight]}>{randomText}折vip</Text>
</View>
<View>
<Text style={styles.detailText}>地点:首都机场{randomText}</Text>
<TouchableOpacity style={[styles.alignRight]}>
<Text style={[styles.button]}>预定</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
row: {
flexDirection: 'row',
alignItems: 'center',
overflow: 'hidden',
},
rowImg: {
flex: 1,
height: 100,
resizeMode: 'stretch',
},
rowContent: {
flex: 3,
padding: 7,
},
titleText: {
fontWeight: 'bold',
fontSize: 14,
},
detailText: {
marginTop: 3,
color: '#999',
fontSize: 12,
},
alignRight: {
position: 'absolute',
top: 0,
right: 0,
},
button: {
padding: 2,
borderRadius: 4,
color: '#fff',
backgroundColor: '#09c',
},
labelWrap: {
flexDirection: 'row',
},
labelText: {
marginRight: 3,
borderRadius: 3,
borderWidth: 1,
borderColor: '#09c',
}
})