前言
去年我寫(xiě)了一個(gè)教程,手把手教你寫(xiě)一個(gè)RN小程序!,里面其實(shí)對(duì)ListView已經(jīng)做了一些詳解,不過(guò)由于那個(gè)項(xiàng)目接口停止維護(hù),再加上RN教程準(zhǔn)備寫(xiě)一個(gè)系列,所以重新寫(xiě)一篇文章來(lái)完善ListView的使用。另外,ListView一般都是配合數(shù)據(jù)來(lái)使用的,所以這里我把網(wǎng)絡(luò)請(qǐng)求也順帶簡(jiǎn)單的講解一下。本文會(huì)使用豆瓣api來(lái)進(jìn)行數(shù)據(jù)的解析。
fetch()
React Native提供了和web標(biāo)準(zhǔn)一致的Fetch API,用于滿(mǎn)足開(kāi)發(fā)者訪(fǎng)問(wèn)網(wǎng)絡(luò)的需求。那么如何使用呢?
fetch使用
fetch('https://api.douban.com/v2/movie/top250')//豆瓣電影Top250
從任意地址獲取數(shù)據(jù),只需要這么寫(xiě)就可以了,把地址傳遞給fetch()方法。
fetch('https://api.douban.com/v2/movie/top250')
//ES6的寫(xiě)法左邊代表輸入的參數(shù)右邊是邏輯處理和返回結(jié)果
.then((response) => response.json())
.then((responseData) => {
this.setState({
data: responseData,
});
})
.done();
以上是fetch通過(guò)get請(qǐng)求獲取的數(shù)據(jù),這個(gè)可以獲取數(shù)據(jù)源data,那么我們登錄注冊(cè)一般都是用的post提交方式,那該如何寫(xiě)呢?
fetch()還有可選的第二個(gè)參數(shù)用來(lái)指定請(qǐng)求的方法,你可以指定header參數(shù),或是指定使用POST方法,又或是提交數(shù)據(jù)等等。
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',//指定POST方法
headers: {//指定header參數(shù)
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({//設(shè)置提交的數(shù)據(jù)
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
.then((response) => response.json())
.then((responseData) => {
//responseData是服務(wù)器返回的data
}
})
.done();
簡(jiǎn)單的fetch()請(qǐng)求就介紹到這里,有想法的同學(xué)可以參考該文章:【翻譯】這個(gè)API很“迷人”——(新的Fetch API)
溫馨提示,iOS默認(rèn)不支持http請(qǐng)求,請(qǐng)?jiān)赬code中設(shè)置
1、在Info.plist中添加NSAppTransportSecurity類(lèi)型Dictionary。
2、在NSAppTransportSecurity下添加NSAllowsArbitraryLoads類(lèi)型Boolean,值設(shè)為YES
組件生命周期
一般來(lái)說(shuō),一個(gè)組件類(lèi)由 extends Component創(chuàng)建,并且提供一個(gè) render方法以及其他可選的生命周期函數(shù)、組件相關(guān)的事件或方法來(lái)定義。
getInitialState()函數(shù) 初始化 this.state 的值,只在組件裝載之前調(diào)用一次。
getDefaultProps()函數(shù) 只在組件創(chuàng)建時(shí)調(diào)用一次并緩存返回的對(duì)象,因?yàn)檫@個(gè)方法在實(shí)例初始化之前調(diào)用,所以在這個(gè)方法里面不能依賴(lài) this 獲取到這個(gè)組件的實(shí)例。
render() 組裝生成這個(gè)組件的 HTML 結(jié)構(gòu) ,必須要有的函數(shù)
生命周期函數(shù)
componentWillMount() 只會(huì)在裝載之前調(diào)用一次,在 render 之前調(diào)用,你可以在這個(gè)方法里面調(diào)用 setState 改變狀態(tài)
componentDidMount() 只會(huì)在裝載完成之后調(diào)用一次,在 render 之后調(diào)用,從這里開(kāi)始可以通過(guò) ReactDOM.findDOMNode(this) 獲取到組件的 DOM 節(jié)點(diǎn)。
componentWillUnmount() 卸載組件觸發(fā)
更新組件時(shí)觸發(fā)的函數(shù):
componentWillReceiveProps()
shouldComponentUpdate()
componentWillUpdate()
componentDidUpdate
ListView
ListView是一個(gè)常用核心組件,用于高效地顯示一個(gè)可以垂直滾動(dòng)的變化的數(shù)據(jù)列表。通過(guò)創(chuàng)建一個(gè)ListView.DataSource數(shù)據(jù)源,然后給它傳遞一個(gè)普通的數(shù)據(jù)數(shù)組,再使用數(shù)據(jù)源來(lái)實(shí)例化一個(gè)ListView組件,并且定義它的renderRow回調(diào)函數(shù),這個(gè)函數(shù)會(huì)接受數(shù)組中的每個(gè)數(shù)據(jù)作為參數(shù),返回一個(gè)可渲染的組件(作為listview的每一行)。
cellRow(data) {
return (
<View >//這個(gè)是cell的視圖
</View>
);
}
render() {
return (
<View style={styles.container}>
<ListView
initiaListSize={1} //指定在組件剛掛載的時(shí)候渲染多少行數(shù)據(jù)。用來(lái)確保首屏顯示合適數(shù)量的數(shù)據(jù)
//onChangeVisibleRows={()=>{}}//當(dāng)可見(jiàn)的行的集合變化的時(shí)候調(diào)用此回調(diào)函數(shù)
//onEndReached={()=>{}}//當(dāng)所有的數(shù)據(jù)都已經(jīng)渲染過(guò),并且列表被滾動(dòng)到距離最底部不足onEndReachedThreshold個(gè)像素的距離時(shí)調(diào)用。配合onEndReachedThreshold使用
onEndReachedThreshold={10} //調(diào)用onEndReached之前的臨界值,單位是像素。
pageSize={3} //每次渲染的行數(shù)
removeClippedSubviews={true}//用于提升大列表的滾動(dòng)性能。需要給行容器添加樣式overflow:'hidden'。(Android已默認(rèn)添加此樣式)。此屬性默認(rèn)開(kāi)啟。
dataSource={this.state.dataSource} //列表依賴(lài)的數(shù)據(jù)源
renderRow={this.cellRow.bind(this)}//(rowData, sectionID, rowID, highlightRow) => renderable 從數(shù)據(jù)源(Data source)中接受一條數(shù)據(jù),以及它和它所在section的ID。返回一個(gè)可渲染的組件來(lái)為這行數(shù)據(jù)進(jìn)行渲染。
style={styles.listView}
/>
</View>
);
}
renderSectionHeader()方法會(huì)為每個(gè)section提供一個(gè)粘性的標(biāo)題
scrollTo(...args),滾動(dòng)到指定的x,y偏移處。
ListView和Fetch()結(jié)合使用
1.新建一個(gè)文件
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
ListView
} from 'react-native';
export default class TestDemo extends Component {
render() {
return (
<View style={styles.container}>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
flex:1,
}
});
2.引入ListView
<ListView initiaListSize={2}
pageSize={2}
dataSource={this.state.dataSource}
renderRow={this.cellRow.bind(this)}
style={styles.listView}
/>
然后根據(jù)文檔添加數(shù)據(jù)源dataSource
constructor(props){
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {dataSource: ds.cloneWithRows([{},])};
}
我們的Cell也必定不能少啊
cellRow(data) {
return (
<TouchableOpacity onPress={()=>this.rowPressed(data)}>
<View>
<View style={styles.cellStyle}>
<Image style={{margin:10,width:100, resizeMode:'contain',height:(WIDTH-40)/2}}
source={{uri: data.images.large}}
/>
<Text style={styles.title}>{data.title}</Text>
</View>
</View>
</TouchableOpacity>
);
}
OK基本上完工,說(shuō)好的fetch呢?別著急,慢慢來(lái)
componentDidMount() {
this.fetchData();
}
fetchData() {
fetch(GET_URL)
//ES6的寫(xiě)法左邊代表輸入的參數(shù)右邊是邏輯處理和返回結(jié)果
.then((response) => response.json())
.then((responseData) => {
if (responseData.subjects) {
//我們需要在數(shù)據(jù)解析完成的時(shí)候來(lái)setdataSource
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData.subjects),
});
} else {
//do Something
Alert.alert('暫時(shí)沒(méi)有數(shù)據(jù)');
}
})
.done
}
恩,測(cè)試的話(huà),GET_URL是https://api.douban.com/v2/movie/top250,
至此基本上已經(jīng)完工,大家可以試著做一下

)
最后
當(dāng)然要附上我們的源碼了,在我的github上:React-Native-Study
后續(xù)會(huì)更新帶Header的ListView和用ListView寫(xiě)的九宮格,喜歡的同學(xué)可以支持一下,么么噠!