ReactNative-綜合案例(02)

最近幾天學了幾個ReactNative組件,總覺得單純的學幾個組件進步慢,所以我打算做一些綜合性的小案例,練習下實戰,我從網上找到一個小案例
,感覺挺好,也學習了很多,代碼內容可能不太一樣,主要區別是:我把RN官方不推薦或者已經放棄了的組件進行了替換,如果有需要的可以互相參考下

接着上篇案例開始寫,這篇文章將會講解如何編寫輪播圖和列表

首先WYHome.js代碼如下:

import React, { Component } from 'react';
import {
    StyleSheet,
    Text,
    View,
    ListView
} from 'react-native';

import Request from '../Utils/WYRequest'
import WYSwiper from './Swiper/WYHomeSwiper'
import WYNewsCell from './WYNewsCell'

export default class WYHome extends Component {
  static defaultProps = {
    api_url: 'http://c.m.163.com/nc/article/headline/T1348647853363/0-20.html?from=toutiao&fn=1&prog=LTitleA&passport=&devId=nTM86EPlcxZu09VdpTEh6aR3%2B%2FQX6x8vHBD3ne3k5bbgOrg%2FIP5DcguSDmtYyWbs&offset=0&size=20&version=14.0&spever=false&net=wifi&lat=DUH4Hf95lyIDaAI03C3RSA%3D%3D&lon=HJ4tj6FL5wRHQxcf5GLEcg%3D%3D&ts=1470728804&sign=1H8K3yy9bMXakmxAlZ9P86meraJtjKQFz5vJuwhjNyl48ErR02zJ6%2FKXOnxX046I&encryption=1&canal=appstore',
    key_word: 'T1348647853363'
  };

  // 構造
  constructor(props){
    super(props);

    // 數據源
    var ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    });
    // 初始狀態
    this.state = {

      dataSource:ds,
      // 廣告
      headerAdArr:[],

      // 判斷是否爲空
      flag:false
    };
  }
  render() {
    return (
      <ListView 
        dataSource={this.state.dataSource}
        renderHeader={this._renderHeader.bind(this)}
        renderRow={this._renderRow.bind(this)}
      >

      </ListView>
    );
  }

  componentDidMount() {
    Request.get(this.props.api_url, (responseData) => {
      // 取出數組
      const dataArr = responseData[this.props.key_word];
      // 臨時數組
      var tempListArr = [], adArr = [];

      // 遍歷數組
      dataArr.forEach((value, index) => {

        if(value.hasAd == 1 || value.hasHead == 1) {
          adArr = value.ads;
        } else {
          tempListArr.push(value);
        }
      });

      // 更新狀態,刷新UI
      this.setState({
        dataSource:this.state.dataSource.cloneWithRows(tempListArr),
        headerAdArr:adArr,
        flag:true
      });
    }, (error) => {
        alert(error);
    });
  }

  // 廣告
  _renderHeader(){
    // 防止空數據
    if(!this.state.flag) return;

    // 容錯
    if(this.state.headerAdArr.length == 0) return;

    return(
      <WYSwiper dataArr={this.state.headerAdArr}></WYSwiper>
    );
  }

  /**
     * 返回具體的行
     * @private
     */
    _renderRow(rowData){
        // 0. 防止空數據
        if(!this.state.flag) return;

        return(
            <WYNewsCell model={rowData} navigator={this.props.navigation}/>
        );
    }
}

其中網絡解析WYRequest抽離成一個幫助類:

module.exports = {
    /**
     * 基於fetch的get方法
     * @method post
     * @param {string} url
     * @param {function} callback 請求成功回調
     */
    get: function(url, successCallback, failCallback){
        fetch(url)
            .then((response) => response.json())
            .then((responseText) => {
                successCallback(responseText);
            })
            .catch(function(err){
                failCallback(err);
            });
    }
};

輪播圖也單獨抽離爲一個組件,方便直接導入:

import React, { Component } from 'react'
import {
  Text,
  View,
  Image,
  Dimensions
} from 'react-native'

import Swiper from 'react-native-swiper'
const { width } = Dimensions.get('window');

export default class extends Component {
  static defaultProps = {
      dataArr: []
  };

  constructor(props) {
    super(props);
    // 初始狀態
    this.state = {
        currentTitle: ''
    };
  }

  render() {
    return (
      <View>
        <Swiper
          style={styles.wrapper}
          height={170}
          onMomentumScrollEnd={(e, state, context) => this.setState({
              // currentTitle: dataArr[state.index].title
          })}
          dot={<View style={{backgroundColor: 'rgba(255,255,255,1)', width: 5, height: 5, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3}} />}
          activeDot={<View style={{backgroundColor: 'orange', width: 8, height: 8, borderRadius: 4, marginLeft: 3, marginRight: 3, marginTop: 3, marginBottom: 3}} />}
          paginationStyle={{
        bottom: 10, left: null, right: 10
        }}
          loop
        >
          {this._renderImage()}
        </Swiper>
      </View>
    );
  }

  _renderImage(){
    // 組件數組
    var itemArr = [];

    const dataArr = this.props.dataArr;
    dataArr.forEach((value, index) => {
      itemArr.push(
        <View key={index} style={styles.slide}>
          <Image
              resizeMode='stretch'
              style={styles.image}
              source={{uri: value.imgsrc}}
              defaultSource={{uri: 'placeholder'}}
          />
          <View style={styles.indicatorViewStyle}>
              <Text style={{color:'#fff'}}>{value.title}</Text>
          </View>
        </View>
      );
    });

    // 返回組件
    return itemArr;
  }
}

const styles = {
  wrapper: {
  },

  slide: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: 'transparent'
  },

  slide1: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#9DD6EB'
  },

  slide2: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#97CAE5'
  },

  slide3: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#92BBD9'
  },

  text: {
    color: '#fff',
    fontSize: 30,
    fontWeight: 'bold'
  },

  image: {
    width,
    flex: 1
  },

  indicatorViewStyle:{
     width,
     height:36,
     backgroundColor:'rgba(0,0,0, 0.4)',
     position:'absolute',
     left:0,
     bottom:0,

     justifyContent:'center',
     paddingLeft:5
  }
};

自定義cellWYNewsCell.js代碼如下:

import React, { Component, PropTypes } from 'react';
import {
    StyleSheet,
    Text,
    View,
    TouchableOpacity,
    Image,
    PixelRatio
} from 'react-native';

var Dimensions = require('Dimensions');
var {width, height} = Dimensions.get('window');

export default class WYNewsCell extends Component {
  // 構造
  constructor(props){
    super(props);

    this.state = {
      model: this.props.model,
      navigator: this.props.navigator,
    };
  }
  render() {
    var model = this.state.model;
    var hahah = this.state.navigator;

    return (
      <TouchableOpacity style={styles.cellStyle} onPress={() => {
        hahah.navigate('WYNewsDetail', {title: model.title});
      }}>
        <Image
            source={ {uri: model.imgsrc} }
            defaultSource={ {uri: 'placeholder'} }
            style={styles.imgStyle}
        />
        <View style={styles.rightViewStyle}>
            <Text
                numberOfLines={2}
            >
                {model.title}
            </Text>
            <View style={styles.rightInnerViewStyle}>
                <Text style={{color:'red', fontSize:14}}>{model.source}</Text>
                <Text style={{color:'#333', fontSize:14}}>{model.ptime}</Text>
            </View>
        </View>
      </TouchableOpacity>
    );
  }
}

const styles = StyleSheet.create({
  cellStyle:{
    borderBottomWidth: 1/PixelRatio.get(),
    borderBottomColor: '#666',

    flexDirection:'row',
    padding:10
  },

  imgStyle:{
    width:90,
    height:90,
    borderRadius:5,
    marginRight:10
  },

  rightViewStyle:{
    flex:1,
    justifyContent:'space-around'
  },

  rightInnerViewStyle:{
    flexDirection:'row',
    justifyContent:'space-between'
  }
});

module.exports = WYNewsCell;

點擊cell跳轉到詳情頁面:

render() {
    var model = this.state.model;
    var hahah = this.state.navigator;

    return (
      <TouchableOpacity style={styles.cellStyle} onPress={() => {
        hahah.navigate('WYNewsDetail', {title: model.title});
      }}>
        <Image
            source={{uri: model.imgsrc}}
            defaultSource={{uri: 'placeholder'}}
            style={styles.imgStyle}
        />
        <View style={styles.rightViewStyle}>
            <Text
                numberOfLines={2}
            >
                {model.title}
            </Text>
            <View style={styles.rightInnerViewStyle}>
                <Text style={{color:'red', fontSize:14}}>{model.source}</Text>
                <Text style={{color:'#333', fontSize:14}}>{model.ptime}</Text>
            </View>
        </View>
      </TouchableOpacity>
    );
  }

難點:
點擊cell跳轉詳情界面,需要將WYHome.js文件當中的navigation傳遞到cell當中:

<WYNewsCell model={rowData} navigator={this.props.navigation}/>

然後在cell當中就可以進行跳轉了。。。。

注意

要想進行跳轉必須在WYMain.js文件中,對視圖進行註冊

const StackNavigators = StackNavigator({
    TabNav: {
      screen: TabNav,
    },

    // 跳轉註冊
    WYNewsDetail: {
      screen: WYNewsDetail,
    }
});

下一篇講解,如何加載網頁

效果圖

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章