1. 程式人生 > >React Native 結合ScrollableTab、RefreshControl和FlatList實現新聞分類列表

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輪播、相簿和相機呼叫、網頁載入。