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= />}
          activeDot={<View style= />}
          paginationStyle=
          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=
              defaultSource=
          />
          <View style={styles.indicatorViewStyle}>
              <Text style=>{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=>{model.source}</Text>
                <Text style=>{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=
            defaultSource=
            style={styles.imgStyle}
        />
        <View style={styles.rightViewStyle}>
            <Text
                numberOfLines={2}
            >
                {model.title}
            </Text>
            <View style={styles.rightInnerViewStyle}>
                <Text style=>{model.source}</Text>
                <Text style=>{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,
    }
});

下一篇讲解,如何加载网页

效果图

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦