跨平台开发ReactNative学习

第一个项目

第一个ReactNative是网络获取电影信息,用列表展示。如图oc中基本的tableview样式

项目源码请见firstReactNative

展示我的学写该项目的学习笔记,掺杂了一些我的个人理解,可能会更清楚一些。原文地址

创建项目

创建第一个项目,项目名字为firstReactNative

react-native init firstReactNative

用终端或Xcode运行该项目,具体步骤见React Native准备工作

如图

引入组件

创建完毕项目打开index.ios.js文件,文件上部有如下代码

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} 

这里是React Native中的一些组件,需要引入。项目中牵扯到图片展示,需要引入Image组件。

顾名思义第一个import是引入组件框架,第二个import是引入几个常用的组件。

AppRegistry 是注册应用组件,应用只有注册之后才能正确渲染,应用只整体注册一次,并不是每个组件都注册,对应该文件最下面的注册应用操作

AppRegistry.registerComponent('firstReactNative', () => firstReactNative);

StyleSheet 是样式创建组件,在const styles = StyleSheet.create()使用。

Text View 是一些常用的控件组件,Image组件添加到这下面,注意要在View后面写,(最后一个后面的,可写可不写)

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

创建模拟数据

在任意位置添加变量数据URLDATA (不要在其他方法{}内添加)

var URLDATA = [
    {title: '标题', year: '2016', posters:{thumbnail: 'http://i.imgur.com/UePbdph.jpg'}}
];

iOS9中http请求需要添加允许任意的请求方式,在info.plist里添加App Transport Security Settings在该字段下选择Allow Arbitrary Loads并设置为YES。原因见iOS9的适配特性

修改组件

渲染组件

class firstReactNative extends Component { 里面更改为如下代码:

render() {
    var movie = URLDATA[0]
    return (
      <View style={styles.container}>
        <Text >{movie.title}</Text>
        <Text>{movie.year}</Text>
        <Image source = {{uri: movie.posters.thumbnail}} />
      </View>
    );
}

movie是拿到的模拟数据分别用Text Image渲染到屏幕上。command + R刷新模拟器运行程序。这时候还看不到图片,因为没有指定图片的宽高

如图

设置组件样式

把原有代码块const styles = StyleSheet.create({});删除掉

创建新的渲染样式

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  thumbnail: {
    width: 53,
    height: 81,
  },
});

并把图片的渲染样式thumbnail添加到组件Image

<Image 
    source = {{uri: movie.posters.thumbnail}}
    style = {styles.thumbnail}
/>

command + R刷新模拟器运行程序。

如图

改变样式排版

现在是文字在上图片在下的样式,需要调整样式,图片在左边,文字在右边。这是基本的tableview样式

styles里添加几个样式

rightContainer: { //存放文字view的样式
    flex: 1, //是让里面存放的元素具有相同的宽度,忽略存放内容。css样式属性。
},
title: {//标题样式
    fontSize: 20,
    marginBottom: 8,
    textAlign: 'center',
},
year: {//简介样式
    textAlign: 'center',
},

修改return ()里面的代码,将新添加的样式添加到相应组件上

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>
);

相比于之前代码,<Image />代码块移动到了<Text>上面,因为image要在文字的左边,从上到下,从左到右渲染,如果还放在text的下面的话,会出现文字在左边,图片在右边的效果,请自行试验。

Text用一个<View>组件包起来,并赋予样式rightContainer,里面有一个flex: 1属性,这个容器的属性宽度会自动变宽,不会因为内容多少而定,会把图片挤压到屏幕边缘

给文字分别添加title year样式,指定的文字的大小以及居中显示。 marginBottom: 8,是让title下面有8像素的距离。

command + R刷新模拟器运行程序。

image

至此,基本的单个样式已完成,如图定义完成tableview里单个cell的样式。下面开始获取网络真是数据,完成列表展示

获取网络数据

Rotten Tomatoes(美国影评网站烂番茄)的api获取数据

在文件开头import的下面定义接口地址变量

var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';

把下面代码放到render()函数之前。在网络获取之前初始化一个null状态,根据this.state.movies == null判断数据是否抓取成功。

constructor(props) {
    super(props);
    this.state = {
        movies: null,
    };
    this.fetchData = this.fetchData.bind(this);
}

添加React组件生命周期方法componentDidMount(),在组件加载完毕之后执行,只执行一次,在这里进行数据请求。

componentDidMount() {
    this.fetchData();
}

fetchData()函数,网络请求

fetchData() {
    fetch(REQUEST_URL)
        .then((response) => response.json())
        .then((responseData) => {
            this.setState({
                movies: responseData.movies,
            });
        })
        .done();
}

修改原来的render函数,修改样式

render() {
    if (!this.state.movies) { //如果没有数据 返回renderLoadingView()
        return this.renderLoadingView();
    }
    var movie = this.state.movies[0];
    return this.renderMovie(movie); //有数据的时候,执行这个函数
}

实现renderLoadingView()函数和renderMovie()函数

renderLoadingView() {//添加加载提示
    return (
        <View style = {styles.container}>
            <Text>
                正在加载电影数据...
            </Text>
        </View>
    );
}
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>
    );
}

command + R刷新模拟器运行程序。这时候得到的数据是网络数据

image

ListView

ListView可以说是ReactNative里的UITableView,会安排视图的渲染,只渲染屏幕上显示的元素,渲染完毕被移出屏幕外的元素会被移除掉。

第一步引入ListView组件,跟上文中引入Image组件一样。

修改render函数,把返回一条数据的代码修改为渲染包含多个电影信息的ListView

render() {
    if (!this.state.loaded) {
        return this.renderLoadingView();
    }
    return (
        <ListView 
            dataSource = {this.state.dataSource}
            renderRow = {this.renderMovie}
            style = {styles.listView}
        />
    );
}

修改constructor(props)代码,不再使用this.state.movies来存放数据,把数据存放到dataSource里面,可以根据布尔值this.state.loaded来判断是否加载完毕

constructor(props) {
    super(props);
    this.state = {
        dataSource: new ListView.DataSource({
            rowHasChanged: (row1, row2) => row1 !== row2,
        }),
        loaded: false,
    };
    this.fetchData = this.fetchData.bind(this);
}

修改fetchData方法,把数据更新到dataSource

fetchData() {
    fetch(REQUEST_URL)
        .then((response) => response.json())
        .then((responseData) => {
            this.setState({
                dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
                loaded: true,
            });
        })
        .done();
}

添加样式listView

listView: {
    paddingTop: 20,
    backgroundColor: '#F5FCFF',
},

command + R刷新模拟器运行程序。达到我们最终要的结果

image

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值