Hello World
react native 官方Hello world示例
import React, { Component } from 'react';
import { AppRegistry, Text } from 'react-native';
class HelloWorldApp extends Component {
render() {
return (
<Text>Hello world!</Text>
);
}
}
// 注意,这里用引号括起来的'HelloWorldApp'必须和你init创建的项目名一致
AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);
我们从import开始来看这个程序:
第一行和第二行都是import xxx from 'xxxxx',这句话的意思大概就是从'xxxxx'文件中引入xxx ,import 语句是es6的内容,关于es6的新特性可以看阮一峰老师的书,后边的文件是一个js文件他只写了文件名没有跟上.js后缀,import和from 之间的内容就是文件中定义的组件。
接下来看 下面class xxx extends Component{}
这个看着有点像JAVA的类继承语句,这也是es6的内容Component是一切界面组件的根类实现界面组件必须要像上面一样继承此类,再看类内的代码render(){returun()}
render的中文意思是渲染这就是组件的渲染函数return括号中的内容就是界面上渲染的内容
最后一句是AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);
我们可以看到registerComponent函数有两个参数第一个参数是一个字符串是项目的名字,第二参数是一个表达式=>
符号也是es6的,内容符号前面是参数列表符号后面是方法体,此语句的意思是以HelloWorldApp组件为根组件渲染这个项目,第二个参数可以替换为你自己想要的方法体,比如:AppRegistry.registerComponent('HelloWorldApp', () => MyApp);
MyApp 是继承自Component的组件。
Props(属性)
第一个官方示例
大多数组件可以在创建的时候可以使用各种参数进行定制,这些参数称为属性Props。下面看一个官方示例
import React, { Component } from 'react';
import { AppRegistry, Image } from 'react-native';
class Bananas extends Component {
render() {
let pic = {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
};
return (
<Image source={pic} style={{width: 193, height: 110}} />
);
}
}
AppRegistry.registerComponent('Bananas', () => Bananas);
这是一段显示一张图片的代码 其中的Image组件带了两个属性分别为source 和style,source属性用于指定图片资源let是es6中新增加的关键字用于指定一个局部变量(详细内容看书),可以注意到source后面pic被一个{}包围,这是在jsx代码中插入js代码的方式{}中可以写js代码。
获取图片的两种方法
1、通过uri加载如上代码所示:
let pic = { uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg' };
2、通过require
let pic = {require('./icon.png')}
require中的字符串是相对地址或者绝对地址,require()中的参数必须是一个字面量而不能是一个变量活常量
let path = './icon.png'
let pic = {require(path)} //这会报错说找不到相应的model
let pic = {require('./icon.png')}//正确
第二个示例
除了组件自带的属性我们也可以添加我们自己的属性,示例如下:
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Greeting extends Component {
render() {
return (
<Text>Hello {this.props.name}!</Text>
);
}
}
class LotsOfGreetings extends Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
AppRegistry.registerComponent('LotsOfGreetings', () => LotsOfGreetings);
上面的代码自定义了一个Greeting组件,使用了{this.props.name}
去初始化组件,Text的组件中本来不包含这个属性,是我们自己加的,我们无需任何声明,只要在使用组件时加入这一个属性即可。
状态(state)
props和state共同控制了一个组件,props在父组件中指定,在指定组件的生命周期中不在改变。对于需要改变的数据我们使用state
一般来说,需要在constructor中初始化state,下面是一个实现文字闪烁效果的例子:
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Blink extends Component {
constructor(props) {
super(props);
this.state = { showText: true };
// 每1000毫秒对showText状态做一次取反操作
setInterval(() => {
this.setState({ showText: !this.state.showText });
}, 1000);
}
render() {
// 根据当前showText的值决定是否显示text内容
let display = this.state.showText ? this.props.text : ' ';
return (
<Text>{display}</Text>
);
}
}
class BlinkApp extends Component {
render() {
return (
<View>
<Blink text='I love to blink' />
<Blink text='Yes blinking is so great' />
<Blink text='Why did they ever take this out of HTML' />
<Blink text='Look at me look at me look at me' />
</View>
);
}
}
AppRegistry.registerComponent('BlinkApp', () => BlinkApp);
样式
在react native中,我们使用js来写样式。所有的核心组件都接受style属性,这些样式和css一样唯一的区别就是,按照js的语法改用了驼峰写法,background-color
->backgroundColor
最简单的写法如下:
<Text style={{backgroundColor:'red',height:50,width:50}} >red<Text>
实际开发推荐用法:在StyleSheet.create中几种定义样式,如下
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';
class LotsOfStyles extends Component {
render() {
return (
<View>
<Text style={styles.red}>just red</Text>
<Text style={styles.bigblue}>just bigblue</Text>
<Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
<Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
</View>
);
}
}
const styles = StyleSheet.create({
bigblue: {
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
},
red: {
color: 'red',
},
});
AppRegistry.registerComponent('LotsOfStyles', () => LotsOfStyles);
宽度和高度
指定宽高
最简单的方式:直接指定height和width,在react native中像素都是luo'ji逻辑像素无单位,例子如下:
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
class FixedDimensionsBasics extends Component {
render() {
return (
<View>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} />
<View style={{width: 150, height: 150, backgroundColor: 'steelblue'}} />
</View>
);
}
};
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent('AwesomeProject', () => FixedDimensionsBasics);
弹性(Flex)宽高
在style中使用flex可以动态的扩张和收缩。在一个父组件只有一个子组件的情况下给子组件指定flex:1
可以使得子组件撑满父组件,但子组件有多个时子组件按照各自的权重分配空间
组件能够撑满剩余空间的前提是父容器的大小不为0,父容器没有指定width和height,也没有指定flex,那么父容器的尺寸就为0。
下面是一个flex使用示例:
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
class FlexDimensionsBasics extends Component {
render() {
return (
// 试试去掉父View中的`flex: 1`。
// 则父View不再具有尺寸,因此子组件也无法再撑开。
// 然后再用`height: 300`来代替父View的`flex: 1`试试看?
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'powderblue'}} />
<View style={{flex: 2, backgroundColor: 'skyblue'}} />
<View style={{flex: 3, backgroundColor: 'steelblue'}} />
</View>
);
}
};
AppRegistry.registerComponent('AwesomeProject', () => FlexDimensionsBasics);
效果如下:
FlexBox布局
一般来说我们使用flexDirection
、alignItems
、justifyContent
来实现大多数的布局
RN的flexbox布局和web中的css布局基本类似,只存在少许的差异。首先默认值不同:
flexDirection
的默认值是cloumn
而不是row
,alignItem
默认值是stretch而不是flex-start,flex只能指定一个值
FlexDirection
style中指定flexDirection可以指定主轴,他有两个取值,默认值column
以及另一个值row
,下面是一个例子:
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
class FlexDirectionBasics extends Component {
render() {
return (
// 尝试把`flexDirection`改为`column`看看
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</View>
);
}
};
AppRegistry.registerComponent('AwesomeProject', () => FlexDirectionBasics);
效果主轴为水平:
JustifyContent
在style中指定justifyContent可以指定子元素沿着主轴的排列方式,选项有flex-start
,center
,flex-end
,space-around
,space-between
。
代码示例:
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
class JustifyContentBasics extends Component {
render() {
return (
// 尝试把`justifyContent`改为`center`看看
// 尝试把`flexDirection`改为`cloumn`看看
<View style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
}}>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</View>
);
}
};
AppRegistry.registerComponent('AwesomeProject', () => JustifyContentBasics);
效果图:
flex-start:
center:
flex-end:
space-around:
space-between:
alignItems
在组件style中指定alignItems可以决定子元素沿着次轴的排列方式。他有四个选项:�flex-start
、center
、flex-end
、stretch
。
想要stretch生效的话子元素在次轴上不能有固定的尺寸
示例代码:
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
class AlignItemsBasics extends Component {
render() {
return (
// 尝试把`alignItems`改为`flex-start`看看
// 尝试把`justifyContent`改为`flex-end`看看
// 尝试把`flexDirection`改为`row`看看
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}>
<View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} />
<View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} />
</View>
);
}
};
AppRegistry.registerComponent('AwesomeProject', () => AlignItemsBasics);
效果图:
flex-start:
center:
flex-end:
stretch:此时我们是将主轴设为row所以垂直方向不能设置也就是不能设置高度。
文本输入
TextInput是一个文本输入的基础组件。有一个名为onChangeeText属性,通过这个属性可以获取组件中的文本,下面是代码例子:
import React, { Component } from 'react';
import { AppRegistry, Text, TextInput, View } from 'react-native';
class PizzaTranslator extends Component {
constructor(props) {
super(props);
this.state = {text: ''};
}
render() {
return (
<View style={{padding: 10}}>
<TextInput
style={{height: 40}}
placeholder="Type here to translate!"
onChangeText={(text) => this.setState({text})}
/>
<Text style={{padding: 10, fontSize: 42}}>
{this.state.text.split(' ').map((word) => word && '🍕').join(' ')}
</Text>
</View>
);
}
}
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent('PizzaTranslator', () => PizzaTranslator);
ScroView的使用
ScrollView是一个通用的容器,可以在其中放入scrollView,下面是一个ScrollView
import React, { Component } from 'react';
import{ AppRegistry, ScrollView, Image, Text, View } from 'react-native'
class IScrolledDownAndWhatHappenedNextShockedMe extends Component {
render() {
return(
<ScrollView>
<Text style={{fontSize:96}}>Scroll me plz</Text>
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Text style={{fontSize:96}}>If you like</Text>
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Text style={{fontSize:96}}>Scrolling down</Text>
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Text style={{fontSize:96}}>What's the best</Text>
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Text style={{fontSize:96}}>Framework around?</Text>
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Image source={require('./img/favicon.png')} />
<Text style={{fontSize:80}}>React Native</Text>
</ScrollView>
);
}
}
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent(
'IScrolledDownAndWhatHappenedNextShockedMe',
() => IScrolledDownAndWhatHappenedNextShockedMe);
ScrollView是用来显示数量不多的元素,它不同于ListView,它会渲染所有的子组件,而不是像ListView一样只渲染可见的部分
效果图如下:
这里讲一下ScrollView的两个属性,第一个
horizontal
,这是一个bool
类型的属性,当它为true
时候他就是一个左右滑动的ScrollView,默认值为false
垂直滑动 ,另一个属性是automaticallyAdjustContentInsets
这个属性当ScrollView作为TabBar或者Navigator后面的时候,ios是否自动调整内容的范围(如果ScrollView或者ListView出现莫名其妙的空白那就将这个属性设置为false),还有一个要点就是ScrollView一定要指定高度(垂直的时候)或宽度(水平的时候)
ListView
ListView组件用于显示垂直滚动列表,它只会渲染其中的可见部分适用于长列表,ListView列表必须有两个属性,dataSource和renderRow。dataSource是列表的数据源,它是一个ListView.DataSource类型对象,redenderRow从dataSource中取数据并渲染。
rowhasChange是ListView的dataSource中的必备属性
下面是一个示例:
import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View } from 'react-native';
class ListViewBasics extends Component {
// 初始化模拟数据
constructor(props) {
super(props);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows([
'John', 'Joel', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin'
])
};
}
render() {
return (
<View style={{paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
</View>
);
}
}
// 注册应用(registerComponent)后才能正确渲染
// 注意:只把应用作为一个整体注册一次,而不是每个组件/模块都注册
AppRegistry.registerComponent('ListViewBasics', () => ListViewBasics);
例子示例如下:
网络
Fetch
React Native提供了和web标准一致的Fetch API
发起网络请求
从任意地址获取数据内容,只需要简单件网址传给fetch方法即可
fetch('https://www.baidu.com')
fetch有许多可以定制的参数,示例如下:
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
这段代码定制了提交方式 请求头和请求体
处理服务器的响应数据
代码示例:
fetch('http://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
fetch语句返回的是一个Promise对象,可以通过then进行异步操作promise.then().then(),then中跟的参数是前面的的返回值。
Navigator
导航器的使用示例:
<Navigator
initialRoute={{ name: 'first', component: LatestRelease }}
configureScene={
(route) => {
return Navigator.SceneConfigs.VerticalUpSwipeJump;
}
}
renderScene={
(route, navigator) => {
let Component = route.component;
return <Component {...route.params} navigator={navigator} />
}
}
>
</Navigator>
export default class LatestRelease extends Component {
_showDetail() {
const {navigator} = this.props;
if (navigator) {
navigator.push({
name: 'Detail',
component: Detail,
})
}
}
render() {
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
return (
<View style={{flex: 1}}>
<View alignItems='center'>
<View style={{backgroundColor: '#F8F8FF'}}><Text>最新发布</Text></View>
<TextInput style={{height: 30, margin: 5, padding: 2, borderColor: 'gray', borderWidth: 1}}
placeholder='搜索'/>
</View>
<View style={{
height: 30,
margin: 5,
backgroundColor: 'deepskyblue',
alignItems: 'center',
flexDirection: 'row'
}}>
<View style={{flex: 1}}>
<Text style={{color: 'white', paddingLeft: 5}}>指标</Text>
</View>
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'flex-end'}}>
<Text style={{color: 'white'}}>同比(%) </Text>
</View>
</View>
<ListView
automaticallyAdjustContentInsets={false}
style={{flex: 7, marginLeft: 5, marginRight: 5}}
dataSource={ds.cloneWithRows(['国内生产总值', '水泥', '固定资产投资(不含农户)', '民间固定资产投资', '房地产开发投资', '社会消费品零售总额']) }
renderRow={(rowData) =>
<TouchableHighlight onPress={this._showDetail.bind(this) } style={{
height: 40,
marginBottom: 5,
borderBottomWidth: 1,
borderBottomColor: 'lightgray'
}} flexDirection='row' alignItems='center'>
<View style={{flex: 1}} flexDirection='row' alignItems='center'>
<View style={{flex: 9}}>
<Text style={{paddingTop: 5, fontSize: 15}}>{rowData}</Text>
<Text style={{}}>2016Q1-2</Text>
</View>
<View style={{flex: 1}}>
<Text style={{fontSize: 18, color: 'red'}}>+6.7</Text>
</View>
</View>
</TouchableHighlight>}
>
</ListView>
<Button style={{backgroundColor: 'red'}} textStyle={{fontSize: 18}}
children={require('./Icon/add_zb_icon1.png')}
>
Hello!word
</Button>
<ButtonComponent
text="添加指标"
textStyle={{letterSpacing: 0,
fontSize: 15,
color: 'black',}}
image={require('./Icon/add_zb_icon1.png')}
shape='rectangle'
height={28}
width={100}
type="primary"
style={{margin:8}}
backgroundColors={['white', 'white']}
/>
</View>
);
}
}
initialRoute 和renderScene是导航器组件中必须声明的属性,initialRoute指定导航器的初始渲染组件,renderScene是渲染场景时的行为