ReactNative-综合案例(02)

本文出自:我的个人博客:http://www.cenzhijun.top/
最近几天学了几个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,
    }
});

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

效果图

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,488评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 楔子 中医世家独女?清华大学高材生?古武界少主?
    秦馥萱阅读 185评论 1 1
  • 我是一片落叶 是秋风把我 吹到这个地方 我还没有死 我还不会死 我只是渐渐凋零 衰草里再不见 蟋蟀的长吟 月光在雨...
    一默1520阅读 356评论 4 9
  • 一直觉得这世界上的告别仪式挺多的,比如喝一场大酒,来一场旅行,或者情不自禁的在车站大哭一场。可是后来才知道,人生中...
    RebornF阅读 94评论 0 1