React Native 学习(三)-- 电影列表展示

16 篇文章 0 订阅
14 篇文章 0 订阅

Part One

组件ListView
<ListView
    // 给listview设置数据源
    // dataSource{}接口用于在数据显示的时候判断哪些数据显示哪些不显示
    dataSource={this.state.dataSource}
    // renderRow表示渲染一行
    // 也就是这里会一条一条的从dataSource中取数据,然后按照
    // renderMovie(movie)里面的规则去显示item,前提就是dataSource里面存放的是movie这种类型的数据
    renderRow={this.renderMovie} 
    // 指定style为listview类型
    style={styles.listView}  
/>

Part Two

下面我们就通过组件ListView来进一步理解和熟悉React Native
官网中提供的有这个示例,不过里面的示例注释不够,对于新手来说里面的内容在理解上还是不太够用,所以我就自己写了一下这个js,其中的注释也很详细,对于新手来说也能看的懂。
下面的内容,大家可以直接把这个内容粘贴下来创建一个新的index.android.js文件放在你的项目中去,然后Reload js查看效果。完整的代码如下:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

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

/**
 * 为了避免骚扰,我们用了一个样例数据来替代Rotten Tomatoes的API
 * 请求,这个样例数据放在React Native的Github库中。
 * 当然,由于众所周知的原因,这个地址可能国内访问也比较困难。
 */
var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';

/*
 * 大家可以把这个类的名字换成你们的项目的名称,然后替换掉你自己的index.android.js文件
 * 注意:这个类型必须和你的项目名称一致,并且文件最后一行通过AppRegistry注册的名称也必须和你的项目名称一致
 */
export default class SampleAppMovies extends Component {

  /**
   * 构造函数
   */
  constructor(props){
    super(props); // 这一句不能省略

    this.state={

        // 这里放我们自定义的state变量及初始值
        movies:null, 

        dataSource:new ListView.DataSource({
            rowHasChanged:(row1, row2) => row1 !== row2, // 控制显示和隐藏 !== 代表不等于符号
        }),

        loaded:false,
    };

    // 在ES6中,如果在自定义的函数中使用了this关键字,则需要对该函数进行绑定操作
    // 否则this的指向不明确就会报错
    // 像下面的代码一样,在constructor 函数中使用bind    也可以使用箭头函数
    this.fetchData = this.fetchData.bind(this);
  }

  /**
   * 渲染 视图显示 方法
   */
  render() {
      // 判断如果movies为null或者loaded为false的话就显示‘正在加载中...’
      if(!this.state.movies || !this.state.loaded){
        return this.renderLoadingView();
      }

      // 显示一个电影条目的时候使用下面的方法
      // var movie = this.state.movies[0];
      // return this.renderMovie(movie);

      return this.renderMovies();
  }

  /**
   * 加载中显示的view
   */
  renderLoadingView(){
    return (
        <View style={styles.container}>
            <Text>
                正在加载电影数据...
            </Text>
        </View> 
    );
  }

  /*
   * 加载成功显示一条结果,这里相当于显示一条item的布局格式
   */
  renderMovie(movie){
      return (
        <View style={styles.container}>
          <Image
            source={{uri:movie.posters.thumbnail}}
            style={styles.thumbnail}
          />

          <View style={styles.rightContainer}>
              <Text style={styles.title}>{movie.title}</Text>
              <Text style={styles.year}>{movie.year}</Text>           
          </View>

        </View>   
      );
  }

  /**
   * 加载成功显示所有结果
   */
  renderMovies(){
    return(
        <ListView
            dataSource={this.state.dataSource} // 给listview设置数据源,dataSource{}接口用于在数据显示的时候判断哪些数据显示哪些不显示
            renderRow={this.renderMovie} // 这里是显示一条item的方法,也就是这里会一条一条的从dataSource中取数据,然后按照renderMovie(movie)里面的规则去显示item
            style={styles.listView}  // 指定style为listview类型
        />  
    );
  }

  /**
   * 这个方法在所有组件加载完成的时候会被调用,只调用一次,一般请求网络的操作会在这个方法中调用
   */
  componentDidMount(){
    this.fetchData();
  }

  /**
   * 自定义  网络请求方法
   */
  fetchData(){

    fetch(REQUEST_URL) // 请求接口
        .then((response) => response.json()) // 将返回结果通过json转为实例对象
        .then((responseData) => {  // 得到想要的数据并重新渲染界面
            // this.setState();方法调用的时候会出发一次重新渲染的操作,也就是会重新执行一次render()方法刷新界面
            this.setState({ 
                // 将结果放在数组中
                movies:responseData.movies,
                // 将结果放在 dataSource中
                dataSource:this.state.dataSource.cloneWithRows(responseData.movies),
                loaded:true,
            });
        });
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1, // 占一份,可能是横向(代表width)也可能是纵向(代表height)
    flexDirection:'row',   // 指定让容器内的成员从左到右横向布局,默认从上到下纵向布局
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
    paddingLeft:12
  },
  thumbnail:{
    width:53,
    height:81
  },
  rightContainer:{
    flex:1 // 占一份
  },
  title:{
    fontSize:20,
    marginBottom:8,
    textAlign:'center'
  },
  year:{
    textAlign:'center'
  },
  listView: {
    paddingTop: 20,
    backgroundColor: '#F5FCFF',
  }
});
// 注册使用
AppRegistry.registerComponent('SampleAppMovies', () => SampleAppMovies);

Part Three

上面的代码示例中,需要我们注意的有以下几点:

1.需要我们引入ListView组件,引入方式如下:
import {
              ...,
              ListView,
              View
            } from 'react-native';
2.需要重写构造方法
  constructor(props){
    super(props); // 这一句不能省略

    this.state={

        movies:null, 

        dataSource:new ListView.DataSource({
            rowHasChanged:(row1, row2) => row1 !== row2, 
        }),

        loaded:false,
    };
    this.fetchData = this.fetchData.bind(this);
  }

在构造中我的写法没有完全模仿官网中的写法,我保留了在state 中的movies,我是想着为之后的操作预留的,大家如果用不着可以删除掉(注意代码中的引用也要删掉)。Componentconstructor(props) 方法中建议写一些初始化的东西,至于其中的stateprops 这两个东西我们在下一篇blog中会详细介绍。

3.重写生命周期方法
/**
   * 这个方法在所有组件加载完成的时候会被调用,只调用一次,一般请求网络的操作会在这个方法中调用
   */
  componentDidMount(){
    this.fetchData(); // 请求接口,处理网络请求 这个是我们自定义的方法
  }

关于Component 组件的生命周期推荐大家看两篇文章React.Component阮一峰的一篇文章 ,组件的生命周期有三种状态:
Mounting:已插入真实 DOM
Updating:正在被重新渲染
Unmounting:已移出真实 DOM
每种状态对应五个生命周期方法,did和will分别在进入某种状态之后之前调用:
componentWillMount() // 增加节点之前
componentDidMount() // 增加节点之后
componentWillUpdate(object nextProps, object nextState) // 重新渲染界面之前
componentDidUpdate(object prevProps, object prevState) // 重新渲染界面之后
componentWillUnmount() // 移除节点之前
另外,React还提供了两种特殊状态的处理函数,方便用户手动去更新界面:
componentWillReceiveProps(object nextProps) // 已经加载的组件的参数变化的时候可以调用
shouldComponentUpdate(object nextProps, object nextState) // 判断组件是否重新渲染时候调用

4.请求接口处理数据
fetchData(){
    fetch(REQUEST_URL) // 请求接口
        .then((response) => response.json()) 
        .then((responseData) => { 
            this.setState({     
                movies:responseData.movies,
    dataSource:this.state.dataSource.cloneWithRows(responseData.movies),
                loaded:true,
            });
        });
}

这里面需要注意的就是接口的返回类型需要是json格式的,解析成功之后通过对象responseData 去得到我们想要的结果就行了。

5.最后需要注意的就是显示结果

我们要为ListView指定数据源,处理item的加载,也就是上面的renderMovie(movie)方法,这个方法在Android中就类似于Adapter中的ViewHolder,用于item的显示。

资料

电影列表示例资料地址:
http://reactnative.cn/docs/0.38/sample-application-movies.html

组件生命周期:
http://www.ruanyifeng.com/blog/2015/03/react.html
https://facebook.github.io/react/docs/react-component.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值