一. 简介
一个核心组件,用于高效地显示一个可以垂直滚动的变化的数据列表。最基本的使用方式就是创建一个ListView.DataSource数据源,然后给它传递一个普通的数据数组,再使用数据源来实例化一个ListView组件,并且定义它的renderRow回调函数,这个函数会接受数组中的每个数据作为参数,返回一个可渲染的组件(作为listview的每一行)。
由于平台差异性,React Native 中的滚动列表组件 ListView 并没有直接映射为 android 中的 ListView 或 iOS 中的 UITableView,而是在ScrollView 的基础上使用 JS 做了一次封装。这样,滚动体验部分由 Native 负责,而 React 部分则专注于组件何时渲染、如何渲染等问题。
二.数据源及结构
数据源默认的格式有三个维度:
第一个维度是 sectionId ,标识属于哪一段, 可以手动指定或隐式地使用数组索引或对象的 key 值;
第二个维度是 rowId ,标识某个数据段下的某一个行,同样可以手动指定或隐式地使用数组索引或对象的 key 值;
第三个维度是具体的数据对象,根据实际的需要而定。
需要注意的是,上面只是 默认的数据格式 ,如果它不符合实际的需求, 完全可以使用自定义的数据结构 。唯一的区别就是需要额外指定给 ListView 数据源中哪些是 id,哪些是 rowData。
DataSource 的构造函数接收以下4个参数(都是可选):
rowHasChanged : 用于在数据变化的时候,计算出变化的部分,在更新时只渲染脏数据;
sectionHeaderHasChanged : 同理,在列表带分段标题时需要实现;
getRowData/getSectionHeaderData : 如果遵循默认的数据源格式,这两个方法就没有必要实现,用内部默认的即可;而当数据源格式是自定义时,需要手动实现这两个方法。
DataSource 的初始化一般在 constructor 方法中
数据源确定后,下一个工作就是列表的渲染。在渲染时发挥重要作用的是 renderRow 属性,它接收数据源中保存的数据对象,并通过返回值确定该行该如何进行展现。我们可以对所有行统一进行展现,也可以根据里面的字段做出不同的展现。在列表包含 sectionHeader 时,还需要实现 renderSectionHeader 方法。
注意:要更新datasource中的数据,请(每次都重新)调用cloneWithRows方法(如果用到了section,则对应cloneWithRowsAndSections方法)。数据源中的数据本身是不可修改的,所以请勿直接尝试修改。clone方法会自动提取新数据并进行逐行对比(使用rowHasChanged方法中的策略),这样ListView就知道哪些行需要重新渲染了。
React Native ListView sticky效果实现
dataBlob{The dataBlob is a data structure (generally an object) that holds all the data powering the ListView}:dataBlob 包含ListView所需的所有数据(section header 和 rows),在ListView渲染数据时,使用 getSectionData 和 getRowData 来渲染每一行数据。 dataBlob 的 key 值包含 sectionID + rowId
sectionIDs[]:用于标识每组section
rowIDs[]:用于描述每个 section 里的每行数据的位置及是否需要渲染。在ListView渲染时,会先遍历 rowIDs 获取到对应的 dataBlob 数据。
简单示例
示例一 (简单的普通数据)
class ListDemo extends Component { constructor(props){ super(props); this.state={ dataSource:new ListView.DataSource({ rowHasChanged:(row1,row2)=> row1!== row2, }), }; } componentWillMount() { this.fetchData(); } render() { return ( <ListView dataSource={this.state.dataSource} renderRow={(rowData)=><Text>{rowData}</Text>} style={styles.list} /> ); } fetchData(){ this.setState({ dataSource: this.state.dataSource.cloneWithRows(['row 1', 'row 2','row 3','row 4','row 5','row 6','row 7','row 8']), }); } const styles = StyleSheet.create({ list:{ paddingTop: 20, backgroundColor: '#F5FCFF', }, container: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, listView: { paddingTop: 20, backgroundColor: '#F5FCFF', }, thumbnail: { width: 53, height: 81, }, rightContainer: {//让rightContainer在父容器中占据Image之外剩下的全部空间。 flex: 1, }, title: { fontSize: 20, marginBottom: 8, textAlign: 'center', }, year: { textAlign: 'center', }, });
效果
示例二(稍复杂的普通数据)
class ListDemo extends Component { constructor(props){ super(props); this.state={ dataSource:new ListView.DataSource({ rowHasChanged:(row1,row2)=> row1!== row2, }), }; } componentWillMount() { this.fetchData(); } render() { if (!this.state.loaded) { //如果movies==null的情况 初始情况 渲染加载视图 return this.renderLoadingView(); } return ( <ListView dataSource={this.state.dataSource} renderRow={this.renderMovie} style={styles.list} /> ); } renderLoadingView() { return ( <View style={styles.container}> <Text> 正在网络上获取电影数据…… </Text> </View> ); } renderMovie(movie) { return ( <View style={styles.container}> <Image source={{uri: movie.posters.thumbnail}} style={styles.thumbnail} /> <View style={styles.rightContainer}> <Text style={styles.title}>{movie.title}</Text> <Text style={styles.year}>{movie.year}</Text> </View> </View> ); } fetchData() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.movies), loaded:true, }); }) .done(); //调用了done() —— 这样可以抛出异常而不是简单忽略 } const styles = StyleSheet.create({ list:{ paddingTop: 20, backgroundColor: '#F5FCFF', }, container: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, listView: { paddingTop: 20, backgroundColor: '#F5FCFF', }, thumbnail: { width: 53, height: 81, }, //让rightContainer在父容器中占据Image之外剩下的全部空间。 rightContainer: { flex: 1, }, title: { fontSize: 20, marginBottom: 8, textAlign: 'center', }, year: { textAlign: 'center', }, });
效果
特殊数据的listview
class ListDemo extends Component { constructor(props){ super(props); var getSectionHeaderData=(dataBlob,sectionID)=>{ return dataBlob[sectionID]; }; var getRowData=(dataBlob,sectionID,rowID)=>{ return dataBlob[sectionID+":"+rowID]; }; this.state={ loaded:false, dataSource:new ListView.DataSource({ getSectionHeaderData:getSectionHeaderData, getRowData:getRowData, rowHasChanged:(row1,row2)=> row1!== row2, sectionHeaderHasChanged:(s1,s2)=>s1!==s2, }), }; } componentWillMount() { this.fetchData(); } render() { if(!this.state.loaded){ return this.renderLoadingView(); } return ( <View style={styles.container}> <View style={styles.header}> <Text style={styles.headerText}>User List</Text> </View> <ListView dataSource={this.state.dataSource} renderRow={this.renderRow} style={styles.list} renderSectionHeader={this.renderSectionHeader} /> </View> ); } renderSectionHeader(sectionData,sectionID){ return ( <View style={styles.section}> <Text style={styles.text}>片头-公司名:{sectionData}</Text> </View> ); } renderRow(rowData,sectionID,rowID){ return ( <View style={styles.row}> <Text style={styles.rowText}>{rowData.name.title}{rowData.name.first}{rowData.name.last}-{sectionID}-{rowID}</Text> </View> ); } renderLoadingView(){ return ( <View style={styles.loadingPage}> <Text>正在加载中。。。</Text> </View> ); } fetchData() { var responseData = { "results": [ { "organization": "马云的淘宝", "id": 12348124, "users": [{ "user": { "gender": "female", "name": {"title": "miss", "first": "marga", "last": "seegers"}, "location": { "street": "9234 kintgenshaven", "city": "epe", "state": "groningen", "zip": "24360" }, "email": "marga.seegers25@example.com", "username": "orangeleopard377", "password": "427900", "salt": "KrIEhHan", "md5": "589a574553250be33f3b1170624ad2d1", "sha1": "b95ebe39ae6119c5d578938b2d0be8abf674d22c", "sha256": "591584f0bcd6ab1700b59f7bad4ef84917d9ad1270a5a3f4fdd0519fd6d6f37e", "registered": "1412818529", "dob": "368162464", "phone": "(468)-937-2959", "cell": "(971)-550-2808", "BSN": "95632864", "picture": { "large": "http://api.randomuser.me/portraits/women/35.jpg", "medium": "http://api.randomuser.me/portraits/med/women/35.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/35.jpg" }, "version": "0.6", "nationality": "NL" }, "seed": "0e4de8b1953a999b06" }, { "user": { "gender": "female", "name": {"title": "miss", "first": "dian", "last": "grinwis"}, "location": { "street": "8484 vismarkt", "city": "oirschot", "state": "flevoland", "zip": "57731" }, "email": "dian.grinwis32@example.com", "username": "redduck583", "password": "slammer", "salt": "RlM7lRMv", "md5": "3956e950cbbf896533aef74c2c82cd89", "sha1": "f75a3a91443900b4d00caae529242bae7619dc67", "sha256": "6bd83fd97fe9eb451778af5640def605d944ad9868c0c5f3a0afe7f265967975", "registered": "1273461100", "dob": "457808604", "phone": "(693)-305-1652", "cell": "(948)-380-2046", "BSN": "21298918", "picture": { "large": "http://api.randomuser.me/portraits/women/59.jpg", "medium": "http://api.randomuser.me/portraits/med/women/59.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/59.jpg" }, "version": "0.6", "nationality": "NL" } }, { "user": { "gender": "female", "name": {"title": "miss", "first": "sky", "last": "van der kemp"}, "location": { "street": "9082 hanengeschrei", "city": "woerden", "state": "noord-brabant", "zip": "87830" }, "email": "sky.van der kemp89@example.com", "username": "beautifullion820", "password": "jameson", "salt": "gpRYYHWG", "md5": "8d3c0c7c2338280d383815eeb93509f6", "sha1": "aba28553b806a84b5c93cb07b15a5eea6ad3dced", "sha256": "bd37728ef45db8e5e2309883da62c85b6d66c555585f915007f4540b8baf73a2", "registered": "1050510726", "dob": "901473870", "phone": "(164)-819-7581", "cell": "(839)-758-4768", "BSN": "97799112", "picture": { "large": "http://api.randomuser.me/portraits/women/10.jpg", "medium": "http://api.randomuser.me/portraits/med/women/10.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/10.jpg" }, "version": "0.6", "nationality": "NL" } }, { "user": { "gender": "male", "name": {"title": "mr", "first": "davi", "last": "van de kerkhof"}, "location": { "street": "4627 a.b.c.-straat", "city": "baarn", "state": "zeeland", "zip": "85733" }, "email": "davi.van de kerkhof88@example.com", "username": "tinyfish856", "password": "mack", "salt": "hDCD5UCo", "md5": "c84ceab40f165ace6d8e91232a6905ce", "sha1": "902f7e0e61e582382b878e6fc52dbe54a8ca6824", "sha256": "f80e5324f69e59171190f38640d811e1b297bf6fa6010b4f051962521b645b9d", "registered": "1309871004", "dob": "94515551", "phone": "(859)-733-3132", "cell": "(772)-233-1220", "BSN": "51713289", "picture": { "large": "http://api.randomuser.me/portraits/men/72.jpg", "medium": "http://api.randomuser.me/portraits/med/men/72.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/72.jpg" }, "version": "0.6", "nationality": "NL" } }, { "user": { "gender": "male", "name": {"title": "mr", "first": "yanick", "last": "van leuveren"}, "location": { "street": "2184 dorstige hartsteeg", "city": "alphen aan den rijn", "state": "zuid-holland", "zip": "27375" }, "email": "yanick.van leuveren88@example.com", "username": "blackgoose35", "password": "moneys", "salt": "HbNeVqXl", "md5": "dbcdaf6a92e48e2dd0b87053a6c0a460", "sha1": "791054281820a850e6b23acd05bd8a0d959bd8c2", "sha256": "691fd48fc1194df987b0840548c4d99b6d763f73a10269f16deb3c9905581af9", "registered": "1082860214", "dob": "676524370", "phone": "(866)-815-8130", "cell": "(936)-599-6632", "BSN": "05350614", "picture": { "large": "http://api.randomuser.me/portraits/men/57.jpg", "medium": "http://api.randomuser.me/portraits/med/men/57.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/57.jpg" }, "version": "0.6", "nationality": "NL" } }] }, { "organization": "马化腾的腾讯", "id": 1235513, "users": [{ "user": { "gender": "female", "name": {"title": "miss", "first": "nicole", "last": "sullivan"}, "location": { "street": "4460 dame street", "county": "westmeath", "state": "nebraska", "zip": "65675" }, "email": "nicole.sullivan32@example.com", "username": "whitemeercat565", "password": "emilia", "salt": "4iMLu9PN", "md5": "9bc08bb89d4b7163734e5a82bc1c913f", "sha1": "9de75c7d5e69bfc5ee6f983ee1e14389a4872fc1", "sha256": "edbac3b6a89cbca7682e39d196cc98250ebd08c562e39bfc421ce6df00779591", "registered": "1182085459", "dob": "1168428275", "phone": "061-325-8502", "cell": "081-708-1316", "PPS": "9813310T", "picture": { "large": "http://api.randomuser.me/portraits/women/69.jpg", "medium": "http://api.randomuser.me/portraits/med/women/69.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/69.jpg" }, "version": "0.6", "nationality": "IE" }, "seed": "5619bbd757e136f605" }, { "user": { "gender": "male", "name": {"title": "mr", "first": "charlie", "last": "snyder"}, "location": { "street": "2432 rookery road", "county": "mayo", "state": "utah", "zip": "37785" }, "email": "charlie.snyder16@example.com", "username": "crazysnake158", "password": "madrid", "salt": "yGk3jsla", "md5": "62bfb188b82a370c81d70c41b08f44fa", "sha1": "55fb0f5f919367773b4311d60158e0155712c76e", "sha256": "e4e5b13aef4cb0767bf000e51ee5ee81b229b917282cc632cc60ba0e4443428c", "registered": "1188946120", "dob": "854921262", "phone": "051-414-5629", "cell": "081-733-0879", "PPS": "7060395T", "picture": { "large": "http://api.randomuser.me/portraits/men/96.jpg", "medium": "http://api.randomuser.me/portraits/med/men/96.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/96.jpg" }, "version": "0.6", "nationality": "IE" } }, { "user": { "gender": "male", "name": {"title": "mr", "first": "adrian", "last": "hawkins"}, "location": { "street": "4294 highfield road", "county": "kerry", "state": "new mexico", "zip": "89723" }, "email": "adrian.hawkins20@example.com", "username": "greenbutterfly955", "password": "lithium", "salt": "BDpOCi72", "md5": "f466f40834aa260d6ab86bee912fc443", "sha1": "4471b33b51ea7bfad7576f6b259d1afb475e93db", "sha256": "115894fc233340373c8d685486ed742e676c9742fefbe2639b74c5f2db963873", "registered": "1023499340", "dob": "1123203166", "phone": "021-701-3515", "cell": "081-472-4664", "PPS": "7895070T", "picture": { "large": "http://api.randomuser.me/portraits/men/80.jpg", "medium": "http://api.randomuser.me/portraits/med/men/80.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/80.jpg" }, "version": "0.6", "nationality": "IE" } }, { "user": { "gender": "female", "name": {"title": "miss", "first": "grace", "last": "johnston"}, "location": { "street": "6826 green lane", "county": "galway", "state": "minnesota", "zip": "47758" }, "email": "grace.johnston99@example.com", "username": "crazypanda878", "password": "dutch", "salt": "gDGBbCyY", "md5": "d91f66fe034218a2975ebd7db4738a12", "sha1": "4df7918a91baf463e9b7e882fff0a70f9cae27f7", "sha256": "ee55cb982b93a9a5c472b3632657e581d581c84e4ff8b2fe74004e965b0e5534", "registered": "1195137230", "dob": "655630404", "phone": "021-808-7639", "cell": "081-330-9635", "PPS": "4498197T", "picture": { "large": "http://api.randomuser.me/portraits/women/28.jpg", "medium": "http://api.randomuser.me/portraits/med/women/28.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/28.jpg" }, "version": "0.6", "nationality": "IE" } }, { "user": { "gender": "female", "name": {"title": "mrs", "first": "rosie", "last": "douglas"}, "location": { "street": "5834 victoria road", "county": "kilkenny", "state": "arizona", "zip": "44906" }, "email": "rosie.douglas24@example.com", "username": "redelephant112", "password": "pissed", "salt": "IHwMrGvi", "md5": "648b75b00311daa164439d898be76cf1", "sha1": "671f6f5c2da4be03e51daea97a7550a49a231f58", "sha256": "89f7406abf60617b3b0b620787f3d85f53ef21f0a2bab9f9f77813429ec9644a", "registered": "1334726180", "dob": "689823354", "phone": "061-117-1724", "cell": "081-737-5541", "PPS": "1120371T", "picture": { "large": "http://api.randomuser.me/portraits/women/13.jpg", "medium": "http://api.randomuser.me/portraits/med/women/13.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/13.jpg" }, "version": "0.6", "nationality": "IE" } }] }, { "organization": "李彦宏的百度", "id": 1237141, "users": [{ "user": { "gender": "female", "name": {"title": "miss", "first": "joyce", "last": "little"}, "location": { "street": "2086 wheeler ridge dr", "city": "saginaw", "state": "hawaii", "zip": "60560" }, "email": "joyce.little62@example.com", "username": "bigbutterfly528", "password": "suan", "salt": "fIfM75bl", "md5": "5b3318e717934073039028c9e5125896", "sha1": "49bb487743a1c03d8fcb8e4d1878a4c7ca8daff3", "sha256": "570824d2765a04ec0d36c3733caf3a6e8a73869fb46463bce59b42ada06a38e4", "registered": "978399204", "dob": "762101147", "phone": "(966)-213-8700", "cell": "(713)-205-8948", "SSN": "472-85-8663", "picture": { "large": "http://api.randomuser.me/portraits/women/73.jpg", "medium": "http://api.randomuser.me/portraits/med/women/73.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/73.jpg" }, "version": "0.6", "nationality": "US" }, "seed": "ce7e3f33874c75ac07" }, { "user": { "gender": "female", "name": {"title": "miss", "first": "peyton", "last": "simmmons"}, "location": { "street": "9904 homestead rd", "city": "albuquerque", "state": "iowa", "zip": "62580" }, "email": "peyton.simmmons73@example.com", "username": "organicrabbit844", "password": "change", "salt": "f0gFY6KT", "md5": "9835af99ec882eb8f29a5620d12181d6", "sha1": "99aedd274a6e5e127c565f0a13f5838acd4c5c07", "sha256": "0822ee2a259d71f8a1cb84e290ca4d75eb2af1ffec69cc72b8e46aa9e791c5d6", "registered": "1144450293", "dob": "275323726", "phone": "(350)-260-4248", "cell": "(738)-528-1621", "SSN": "231-83-6520", "picture": { "large": "http://api.randomuser.me/portraits/women/22.jpg", "medium": "http://api.randomuser.me/portraits/med/women/22.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/22.jpg" }, "version": "0.6", "nationality": "US" } }, { "user": { "gender": "female", "name": {"title": "miss", "first": "ruby", "last": "palmer"}, "location": { "street": "8796 crockett st", "city": "aurora", "state": "wisconsin", "zip": "26266" }, "email": "ruby.palmer60@example.com", "username": "organicbutterfly558", "password": "password", "salt": "lEcGY4xC", "md5": "752c778c0f0b6d68cd61b636c75d1ddd", "sha1": "3d182fbcb725f5178f8a52372f7989f9ee40eee9", "sha256": "e5be4319e50d7208eb8e5f813fa4c9566e2e2a5e078e4d9c82440723381025de", "registered": "1036616387", "dob": "734179936", "phone": "(258)-181-9139", "cell": "(396)-259-8782", "SSN": "291-14-3517", "picture": { "large": "http://api.randomuser.me/portraits/women/40.jpg", "medium": "http://api.randomuser.me/portraits/med/women/40.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/40.jpg" }, "version": "0.6", "nationality": "US" } }, { "user": { "gender": "female", "name": {"title": "miss", "first": "robin", "last": "perkins"}, "location": { "street": "9001 brown terrace", "city": "louisville", "state": "texas", "zip": "24874" }, "email": "robin.perkins25@example.com", "username": "crazylion493", "password": "seth", "salt": "Qez53XZr", "md5": "343d690344f146b8b9b0fecd0470e8bc", "sha1": "fbb6f4a9a5c2ab08784560461401747bf420681a", "sha256": "52dfea4261c4389030c4d8d681c6878a119d56e7ba16bd5a19872ba7ef87ced3", "registered": "1157078698", "dob": "672848315", "phone": "(825)-244-5953", "cell": "(464)-502-6407", "SSN": "599-65-7688", "picture": { "large": "http://api.randomuser.me/portraits/women/81.jpg", "medium": "http://api.randomuser.me/portraits/med/women/81.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/81.jpg" }, "version": "0.6", "nationality": "US" } }, { "user": { "gender": "female", "name": {"title": "miss", "first": "hailey", "last": "cunningham"}, "location": { "street": "9533 e little york rd", "city": "houston", "state": "tennessee", "zip": "36238" }, "email": "hailey.cunningham87@example.com", "username": "organicgorilla912", "password": "ducks", "salt": "EncA1Tp3", "md5": "7b8d57609043dc4947d1a65993ae6833", "sha1": "c293015adfa2b897524f2ff56cf55864b66d8c45", "sha256": "32de293aeb56fbe00f9f460e8c4f287422adbb4c14c70574bb7298aa401d78c0", "registered": "1129991594", "dob": "716892742", "phone": "(429)-446-7246", "cell": "(648)-377-8894", "SSN": "325-61-6120", "picture": { "large": "http://api.randomuser.me/portraits/women/33.jpg", "medium": "http://api.randomuser.me/portraits/med/women/33.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/33.jpg" }, "version": "0.6", "nationality": "US" } }] }, { "organization": "周鸿祎的360", "id": 1727272, "users": [{ "user": { "gender": "male", "name": {"title": "mr", "first": "tommy", "last": "stanley"}, "location": { "street": "5251 station road", "county": "kildare", "state": "michigan", "zip": "81572" }, "email": "tommy.stanley95@example.com", "username": "lazygorilla313", "password": "&", "salt": "DD5UcgD3", "md5": "2155c170ed25a160f6202289bbb26aa5", "sha1": "08d8a9272c02cf04ca91502156e3382c5393b4e1", "sha256": "1d96aba82ee2d70ab4c09ba3a5bdeab7499143e740924e239d76fccafc299115", "registered": "1182422920", "dob": "986003528", "phone": "071-795-0091", "cell": "081-127-4151", "PPS": "8761806T", "picture": { "large": "http://api.randomuser.me/portraits/men/15.jpg", "medium": "http://api.randomuser.me/portraits/med/men/15.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/15.jpg" }, "version": "0.6", "nationality": "IE" }, "seed": "ccfb395bd154809f05" }, { "user": { "gender": "female", "name": {"title": "miss", "first": "rose", "last": "gregory"}, "location": { "street": "5638 denny street", "county": "donegal", "state": "connecticut", "zip": "87034" }, "email": "rose.gregory66@example.com", "username": "bigtiger841", "password": "redhead", "salt": "Pii33pqL", "md5": "ea3043ea9b36202218760e1e20c1a698", "sha1": "dd38287733289745b81c9f132c40dd14bc3b7e1d", "sha256": "f4c745bd9af6d19bf64ea40ba1461a7443e9fcd91df11635570c34ce4c0fa771", "registered": "1225817453", "dob": "946403496", "phone": "021-686-6277", "cell": "081-578-3583", "PPS": "8607168T", "picture": { "large": "http://api.randomuser.me/portraits/women/82.jpg", "medium": "http://api.randomuser.me/portraits/med/women/82.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/women/82.jpg" }, "version": "0.6", "nationality": "IE" } }, { "user": { "gender": "male", "name": {"title": "mr", "first": "gilbert", "last": "jennings"}, "location": { "street": "5801 o'connell street", "county": "dún laoghaire–rathdown", "state": "indiana", "zip": "39404" }, "email": "gilbert.jennings17@example.com", "username": "brownpanda771", "password": "cecile", "salt": "1obuFJot", "md5": "b9cec0adf70102f2f2864babd802c52c", "sha1": "6f38fc8fe8fc24688f40cb36d9deaeaddf6342ee", "sha256": "72d3b4199b7e5ec07388ce7b1fe250c1b4c7b89331dd433daa01409b4e3946a9", "registered": "1412592435", "dob": "303641620", "phone": "011-280-5054", "cell": "081-101-8479", "PPS": "9825189T", "picture": { "large": "http://api.randomuser.me/portraits/men/2.jpg", "medium": "http://api.randomuser.me/portraits/med/men/2.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/2.jpg" }, "version": "0.6", "nationality": "IE" } }, { "user": { "gender": "male", "name": {"title": "mr", "first": "alexander", "last": "howell"}, "location": { "street": "6676 mill road", "county": "limerick", "state": "california", "zip": "50326" }, "email": "alexander.howell89@example.com", "username": "crazypanda484", "password": "ncc1701a", "salt": "cSQ9stxf", "md5": "1e27d0c330372b8dc2e88dc6f34d9ebf", "sha1": "c5ac1af9831f9d2bd4f6f4a54374f0b4d6055447", "sha256": "1958dc5e8d42a7f1ab652591ff5be2a5ab6d13ff41e3f607c70594e6981ba841", "registered": "1329755694", "dob": "1062450998", "phone": "041-809-5573", "cell": "081-513-1057", "PPS": "6067438T", "picture": { "large": "http://api.randomuser.me/portraits/men/73.jpg", "medium": "http://api.randomuser.me/portraits/med/men/73.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/73.jpg" }, "version": "0.6", "nationality": "IE" } }, { "user": { "gender": "male", "name": {"title": "mr", "first": "earl", "last": "banks"}, "location": { "street": "5035 ormond quay", "county": "limerick", "state": "hawaii", "zip": "55569" }, "email": "earl.banks94@example.com", "username": "organickoala180", "password": "1966", "salt": "RclxfBaU", "md5": "8071292ec92ad705c6be09b573d8bd8c", "sha1": "9bdf901a581bf153054b56e3ab02bf1457aa0b1f", "sha256": "bb14430710b45d1b72ec303c2bf529a79abae1e411d9c65205220c47061cd190", "registered": "1336596882", "dob": "535265745", "phone": "031-142-5899", "cell": "081-285-1416", "PPS": "5891844T", "picture": { "large": "http://api.randomuser.me/portraits/men/26.jpg", "medium": "http://api.randomuser.me/portraits/med/men/26.jpg", "thumbnail": "http://api.randomuser.me/portraits/thumb/men/26.jpg" }, "version": "0.6", "nationality": "IE" } }] } ] }; var organizations = responseData.results; var length = organizations.length; var dataBlob = {}; var sectionIDs = []; var rowIDs = []; var users; var organization; var user; var i; var userLength; var j; for (i = 0; i < length; i++) { organization = organizations[i]; sectionIDs.push(organization.id); dataBlob[organization.id] = organization.organization; users = organization.users; userLength = users.length; rowIDs[i] = [];//rowIDs是一个二维数组 for (j = 0; j < userLength; j++) { user = users[j].user; rowIDs[i].push(user.md5); dataBlob[organization.id + ":" + user.md5] = user; } } this.setState({//注意写法 不要加= dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlob, sectionIDs, rowIDs), loaded: true }); } } const styles = StyleSheet.create({ container: { flex: 1, }, listView: { paddingTop: 20, backgroundColor: '#F5FCFF', }, header:{ height:60, justifyContent:'center', alignItems:'center', paddingTop:25, backgroundColor:'#3F51B5', }, headerText:{ fontSize:20, color:'white', fontWeight:'bold', }, section:{ backgroundColor:'#2196F3', justifyContent:'center', alignItems:'center', fontSize:18, flexDirection:'column', padding:5, }, row:{ paddingVertical:20, borderTopColor:'white', borderLeftColor:'white', borderRightColor:'white', borderBottomColor:'#E0E0E0', borderWidth:1, }, rowText:{ color: '#212121', fontSize: 16 }, loadingPage:{ flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, });
效果
三.属性
-
ScrollView props...
这意味着ListView可以使用所有ScrollView的属性。 - dataSource ListViewDataSource
ListView.DataSource实例(列表依赖的数据源) - initialListSize number
指定在组件刚挂载的时候渲染多少行数据。用这个属性来确保首屏显示合适数量的数据,而不是花费太多帧逐步显示出来。 - onChangeVisibleRows function
(visibleRows, changedRows) => void
当可见的行的集合变化的时候调用此回调函数。visibleRows 以 { sectionID: { rowID: true }}的格式包含了所有可见行,而changedRows 以{ sectionID: { rowID: true | false }}的格式包含了所有刚刚改变了可见性的行,其中如果值为true表示一个行变得可见,而为false表示行刚刚离开可视区域而变得不可见。
- onEndReached function
当所有的数据都已经渲染过,并且列表被滚动到距离最底部不足onEndReachedThreshold个像素的距离时调用。原生的滚动事件会被作为参数传递。译注:当第一次渲染时,如果数据不足一屏(比如初始值是空的),这个事件也会被触发,请自行做标记过滤。 - onEndReachedThreshold number
调用onEndReached之前的临界值,单位是像素。 - pageSize number
每次事件循环(每帧)渲染的行数。 - removeClippedSubviews bool
用于提升大列表的滚动性能。需要给行容器添加样式overflow:'hidden'。(Android已默认添加此样式)。此属性默认开启。 - renderFooter function
() => renderable
页头与页脚会在每次渲染过程中都重新渲染(如果提供了这些属性)。如果它们重绘的性能开销很大,把他们包装到一个StaticContainer或者其它恰当的结构中。页脚会永远在列表的最底部,而页头会在最顶部。 - renderHeader function
- renderRow function
rowData, sectionID, rowID, highlightRow) => renderable
从数据源(Data source)中接受一条数据,以及它和它所在section的ID。返回一个可渲染的组件来为这行数据进行渲染。默认情况下参数中的数据就是放进数据源中的数据本身,不过也可以提供一些转换器。
如果某一行正在被高亮(通过调用highlightRow函数),ListView会得到相应的通知。当一行被高亮时,其两侧的分割线会被隐藏。行的高亮状态可以通过调用highlightRow(null)来重置。 - renderScrollComponent function
(props) => renderable
指定一个函数,在其中返回一个可以滚动的组件。ListView将会在该组件内部进行渲染。默认情况下会返回一个包含指定属性的ScrollView。 - renderSectionHeader function
(sectionData, sectionID) => renderable
如果提供了此函数,会为每个小节(section)渲染一个粘性的标题。
粘性是指当它刚出现时,会处在对应小节的内容顶部;继续下滑当它到达屏幕顶端的时候,它会停留在屏幕顶端,一直到对应的位置被下一个小节的标题占据为止。 - renderSeparator function
(sectionID, rowID, adjacentRowHighlighted) => renderable
如果提供了此属性,一个可渲染的组件会被渲染在每一行下面,除了小节标题的前面的最后一行。在其上方的小节ID和行ID,以及邻近的行是否被高亮会作为参数传递进来。 - scrollRenderAheadDistance number
当一个行接近屏幕范围多少像素之内的时候,就开始渲染这一行。 - stickyHeaderIndices [number](ios)
一个子视图下标的数组,用于决定哪些成员会在滚动之后固定在屏幕顶端。举个例子,传递stickyHeaderIndices={[0]}会让第一个成员固定在滚动视图顶端。这个属性不能和horizontal={true}一起使用。
四. 方法
- getMetrics()
导出一些用于性能分析的数据。 - scrollTo(...args)
滚动到指定的x, y偏移处,可以指定是否加上过渡动画。