React Native 結合ScrollableTab、RefreshControl和FlatList實現新聞分類列表
正好剛開始學RN,熟悉一下控制元件和基本使用。
涉及的知識點:
1、fetch網路請求,get 拼接引數,解析json。
2、ScrollableTabView、ScrollableTabBar 分類佈局。
3、FlatList 資料列表。
4、Navigation 路由攜帶引數跳轉。
5、下拉重新整理,結合了 Tab 切換資料更新
需要匯入到 RN 的第三方庫:
react-native-scrollable-tab-view
匯入方法:
1、在專案的根路徑使用下面命令列
npm install react-native-scrollable -tab-view --save
2、檢查專案的 package.json 中的 dependencies 下是否新增進來了,如果沒有就手動依賴下,版本號要一致。
https://badge.fury.io/js/react-native-scrollable-tab-view
"dependencies": {
"react": "^16.3.0-alpha.1",
"react-native": "0.54.4",
"react-native-deprecated-custom-components": "latest",
"react-native-image-picker" : "^0.26.7",
"react-native-scrollable-tab-view": "^0.8.0",
"react-native-swiper": "^1.5.13",
"react-navigation": "^1.5.11"
}
建議安裝 rnmp 自動依賴工具,這樣就不需要在導包的時候再手動去新增本地依賴。
npm install rnpm -g
rnpm link
頁面佈局
1、可滾動的 TabView
使用前需要先匯入到當前 js
import ScrollableTabView, { DefaultTabBar, ScrollableTabBar } from 'react-native-scrollable-tab-view'
DefaultTabBar 和 ScrollableTabBar 是可選擇是否超出螢幕滾動。前者適用於固定的 Tabbar。後者適用於有多種分類的滾動 Tab。
onChangeTab 是 Tab 點選切換的監聽,在這裡可以執行重新整理等效果。
return (
<ScrollableTabView
initialPage={0}
renderTabBar={() => <ScrollableTabBar/>}
tabBarUnderlineStyle={{}}
onChangeTab={(obj) => {
this._onRefresh(news[obj.i])
}}
>
<Text tabLabel='頭條'/>
<Text tabLabel='社會'/>
<Text tabLabel='國內'/>
<Text tabLabel='國際'/>
<Text tabLabel='娛樂'/>
<Text tabLabel='體育'/>
<Text tabLabel='軍事'/>
<Text tabLabel='科技'/>
<Text tabLabel='財經'/>
<Text tabLabel='時尚'/>
</ScrollableTabView>
)
2、下拉重新整理Refresh+FlatList
FlatList 和 ListView 一樣,不過 FlatList 處理列表的效率更高,所以建議使用,而且內建的方法有支援 iOS 和 Android 平臺的下拉重新整理效果。
而且給 List 新增分割線和 Header 也很簡單。
RefreshControl 就是下拉重新整理的佈局,Android 和 iOS 在重新整理樣式上有所不同。
return (
<FlatList
data={this.state.result.data}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
ListHeaderComponent={this._headerTabView()}
ItemSeparatorComponent={this._itemDivide}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this,this.state.newsType)}
/>
}
/>
)
3、列表的Item佈局
需要在外層使用 TouchableOpacity 獲取整個 View 的點選事件。
通過 item 展示和解析資料。在 RN 中不需要定義每個 json 資料的欄位名稱 。所以在解析的時候直接使用引數名呼叫就能拿到資料。
_renderItem = ({item, index}) => {
return (
<TouchableOpacity
activeOpacity={0.5}
onPress={this.itemClick.bind(this, item, index)}>
<View style={{backgroundColor: '#ffffff', padding: 10, flexDirection: 'row'}}>
<Image source={{uri: item.thumbnail_pic_s02}} style={styles.imgStyle}/>
<View style={{flex: 1, flexDirection: 'column'}}>
<Text style={{
paddingRight: 10,
marginLeft: 10,
width: screenWidth * 0.65,
height: 80 * 0.7
}}>{item.title}</Text>
<View style={{flexDirection: 'row', paddingLeft: 10, paddingRight: 10}}>
<Text style={styles.subTitle}>{item.category + ' ' + item.author_name}</Text>
<Text style={styles.subTitle}> {item.date}</Text>
</View>
</View>
</View>
</TouchableOpacity>
)
}
具體實現
1、宣告一些變數
為了方便檢視獲取到的 json 這裡直接按照 API 返回的格式去定義變數。
constructor (props) {
super(props)
//在這裡定義json返回的key
this.state = {
//控制分類展示
isShow: false,
//分類
newsType: 'top',
//下拉重新整理
refreshing: false,
//data資料
resultJson: null,
error_code: '',
reason: '',
result: {
data: ''
}
}
}
2、通過網路獲取資料來源
這裡我使用了一個阿里的新聞 API 。
需要在請求的時候將申請到的 appCode 以新增請求頭的方式提供給 API 。
如果不需要指定獲取新聞的型別,則不需要提供 type 型別。
// type型別:top(頭條,預設),shehui(社會),guonei(國內),guoji(國際),yule(娛樂),tiyu(體育)junshi(軍事),keji(科技),caijing(財經),shishang(時尚)
fetch 就是執行網路請求的入口。
第一個 .then 是為了指定獲取到的 json 以什麼樣的格式返回,如果需要解析可以直接返回 json 格式,方便下面的解析操作。
同時在成功拿到資料之後,需要將重新整理狀態設定為 false ,關閉下拉重新整理的狀態。
第二個 .then 就是通過第一個返回的型別資料,已經格式化好了。只需要解析並賦值就行。
同樣當遇到請求錯誤的情況,通過 catch 丟擲異常,在方法內處理異常。
const header = new Headers()
getRequest (url, type) {
/*網路請求的配置*/
header.append('Authorization', appCode)
const opts = {
method: 'GET',
headers: header,
}
fetch(url + '?type=' + type, opts)
.then((response) => {
this.setState({refreshing: false})
return response.json()
})
.then((responseJson) => {
this.setState({
resultJson: responseJson,
error_code: responseJson.error_code,
reason: responseJson.reason,
result: responseJson.result,
data: responseJson.result.data,
})
// alert(this.state.reason)
})
.catch((error) => {
alert(error)
})
}
3、下拉重新整理
在 RefreshControl 佈局的 onRefresh 方法中呼叫。呼叫的時候,重新開啟下拉重新整理的效果。
//下拉重新整理
_onRefresh (type) {
this.setState({refreshing: true})
this.getRequest(newsUrl, type)
}
4、其它
1.
componentDidMount 是在 render 方法進來之後立即呼叫的方法。
類似於 Android上的onViewCreate 方法,一般在這個方法內可以先進行網路請求,訊息訂閱等操作。
componentDidMount () {
this.getRequest(newsUrl, this.state.newsType)
}
2.
跳轉需要用到路由,關於路由的使用有時間再整理。
//列表點選跳轉事件
itemClick (item, index) {
// alert('新聞標題:' + item.author_name + '\n時間:' + item.date+'\n'+item.thumbnail_pic_s);
this.props.navigation.navigate('Details', {
title: item.title,
url: item.url,
})
}
3.
//List列表分割線
_itemDivide = () => {
return (
<View style={{height: 10}}/>
)
}
關於
- 語法使用ES6標準
- React Native 版本 0.54.4
Demo:https://github.com/wapchief/ReactNativeDemo
有興趣一起學習的朋友可以關注下,將持續更新學習進度,在 Demo 上體現。
目前其它實現的功能有:banner輪播、相簿和相機呼叫、網頁載入。