React Native v0.55 学习笔记1
RN 是基于 React 的思想,相比于 web 的一些组件,RN 使用的是基于原生( android、ios )的组件。所以想用 RN 开发应用的话,就需要了解一些 React 方面的概念。例如 JSX,component,state 和 props。
Hello World
- RN 使用的是 JavaScript ,支持 ES6 的语法,官方文档中的示例大量使用了 ES6 的新特性。
- 在 UI 方面则是主要使用 JSX ——一种可以在 XML 标签中包裹 js 语句的语法。RN 内置很多标签,也支持自定义标签。
- Component 一个完整的应用必然是由许多个 component 组成的。一个 component 可以非常的简单,唯一需要做的事情就是实现
render
函数,这个函数用来返回 JSX 用以渲染 UI.
Props
大多数的
component
都会通过不同的参数来实现自定义的不同功能,这些参数就被称为props
- 例如 RN 中的
Image
标签,其中source
这个属性就是用来控制图片源的。
import React, { Component } from 'react';
import { AppRegistry, Image } from 'react-native';
export default 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}}/>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => Bananas);
- JSX 语法中,标签内部,使用一对花括号
{}
内容可以是 js 的表达式。 - 使用
this.props
在自定义的component
的render
方法中可以获取外部传入的参数,见下面的代码块。 - 下面的例子中,使用到了自定义
component
,在 JSX 中像内置的标签一样使用。 View
是一个非常常用容器标签,也是最基本的 UI 控件之一,支持flexbox
布局、style
、触摸事件处理以及无障碍功能处理。
import React, { Component } from 'react';
import { AppRegistry, Text, View } from 'react-native';
class Greeting extends Component {
render() {
return (
<Text>Hello {this.props.name}!</Text>
);
}
}
export default class LotsOfGreetings extends Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => LotsOfGreetings);
State
props
和state
是控制component
的两种数据类型。前者由父类或者外部传入,在整个控件的生命周期中是固定不变的;后者则是用于一些有变化的数据
- 通常来说,在
constructor
方法中初始化state
。 - 通常来说,使用
this.setState()
方法来改变state
的值。
import React,{Component} from 'react';
import {Text,Image,View} from 'react-native';
class Greeting extends Component{
constructor(props){
super(props);
this.state = {isShowingText:true};
setInterval(()=>{
this.setState(previousState=>{
return { isShowingText: !previousState.isShowingText };
})
},1000);
}
render() {
let disPlay = this.state.isShowingText ? this.props.name : ' ';
return (
<Text style={{color:'#045d51'}}>{disPlay}</Text>
);
}
}
export default class HelloWorldApp extends Component{
render(){
return(
<View style={{alignItems:'center'}}>
<Greeting name='liu'/>
<Greeting name='liulin'/>
<Greeting name='liuru'/>
</View>
);
}
}
- 实际使用中,很少有直接使用定时器来改变
state
的状态,而是跟踪数据流的变动。可以使用像Redux
类似的状态容器来控制数据流,上面的例子中,可以使用Redux
来改变state
而不是直接调用setState
方法。 - 当
setState
方法被调用时,标签所在的component
会被重新渲染。这块的工作机制和React.js
是一致的(暂时还没有去了解)。
Style
- 在 RN 中,使用 JS 的方式来定义组件的样式。所有的核心组件都支持名为
style
的属性,样式的属性名和属性值基本与 web 下 css 一致,只不过命名方式变成了驼峰式。 style
的属性可以是一个简单的 JS 对象,可以传入一个对象数组,对象数组中的对象如果有属性重复,以最后一个同名属性为准,这样也是实现了样式的继承。- 建议使用
StyleSheet.create({})
的方式来构建复用性比较高的样式对象。
export default class HelloWorldApp extends Component{
render(){
return(
<View style={{alignItems:'center'}}>
<Text style={styles.red}>just Red</Text>
<Text style={styles.bigBlue}>just blue</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'
}
});
宽高
height
和width
分别表示控件的高度和宽度,需要注意到的是,宽度和高度的单位是与设备实际像素宽高无关的逻辑像素点(感觉类似 Android 中的 dp 和 sp 的感觉,具体的换算还需要研究)。- 直接设置宽高的值,会使得控件在不同尺寸的屏幕上展示相同的大小。
<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>
- 除了指定具体数值的方式外,宽高还可以弹性指定,利用
flex
这个属性,这个属性的属性值为数字,表示在允许的范围内,按照flex
的值的比例动态设置宽高,类比于 Android 中LinearLayout
的layout_weight
属性。但是需要注意的是,子控件使用flex
属性且生效的前提是,父控件的宽高不为0,否则是不可见的。
<View style={{flex:1}}>
<View style={{flex:1,backgroundColor:'powderblue'}}/>
<View style={{flex:2,backgroundColor:'skyblue'}}/>
<View style={{flex:3,backgroundColor:'steelblue'}}/>
</View>
基本布局 FlexBox
使用
FlexBox
进行布局,使用flexbox
的策略可以指定一个容器内部子控件的布局方式,有三种基本的布局样式,flexDirection
和alignItems
和justifyContent
。
- Flex Direction
在component
的style
属性中添加flexDirection
属性是确定子控件布局的坐标轴主轴是哪个。可选属性值有四个,row
、row-reverse
、column
(默认选项)和column-reverse
。
如何理解坐标轴主轴
row
代表的是x轴,即子控件在x轴方向上按照布局顺序从左到右顺序布局,x轴的方向是左右方向,所以展示效果上来看,就是水平布局(horizontal)
column
代表的是y轴,即子控件在y轴方向上按照布局顺序从上到下顺序布局,y轴的方向是上下方向,所以展示效果是纵向布局(vertical)
<View>
<View style={{height:200,flexDirection:'row'}}>
<View style={{flex:1,backgroundColor:'powderblue'}}/>
<View style={{flex:2,backgroundColor:'skyblue'}}/>
<View style={{flex:3,backgroundColor:'steelblue'}}/>
</View>
<View style={{height:200,flexDirection:'column'}}>
<View style={{flex:3,backgroundColor:'powderblue'}}/>
<View style={{flex:2,backgroundColor:'skyblue'}}/>
<View style={{flex:1,backgroundColor:'steelblue'}}/>
</View>
</View>
row-reverse
和column-reverse
则是颠倒了主轴方向,这个方向指的是布局绘制方向,以row
举例默认状态下是从左侧开始,从左到右顺序绘制,加上-reverse
后,变成了从右侧开始,从右到左顺序绘制,并且justifyContent
的属性值的含义也随着坐标轴方向的变化而取反了。
<View style={{
height:100,
flexDirection:'row',
justifyContent:'flex-start',
alignItems:'center',
backgroundColor:'#878787'
}}>
<View style={[styles.hw50,{backgroundColor:'#0bffd3'}]}/>
<View style={[styles.hw50,{backgroundColor:'powderblue'}]}/>
<View style={[styles.hw50,{backgroundColor:'skyblue'}]}/>
<View style={[styles.hw50,{backgroundColor:'steelblue'}]}/>
</View>
<View style={{height:20}}/>
<View style={{
height:100,
flexDirection:'row-reverse',
justifyContent:'flex-end',
alignItems:'center',
backgroundColor:'#878787'
}}>
<View style={[styles.hw50,{backgroundColor:'#0bffd3'}]}/>
<View style={[styles.hw50,{backgroundColor:'powderblue'}]}/>
<View style={[styles.hw50,{backgroundColor:'skyblue'}]}/>
<View style={[styles.hw50,{backgroundColor:'steelblue'}]}/>
</View>
Justify Content
在component
的style
属性中添加justifyContent
属性是确定子控件在布局坐标轴主轴上的布局方式是哪个。可以选属性值有六个。需要特别注意的是,这个属性作用于所有子控件,即需要将所有子控件作为一个整体来看。flex-start
沿着主轴起始方向布局,等同于 AndroidRelativeLayout
中的layout_alignParentStart
,即当flex:row
时,等同于layout_alignParentLeft
,当flex:column
时,等同于layout_alignParentTop
;flex-end
沿着主轴尾部方向布局,等同于 AndroidRelativeLayout
中的layout_alignParentEnd
,即当flex:row
时,等同于layout_alignParentRight
,当flex:column
时,等同于layout_alignParentBottom
;center
沿着主轴整体居中排列;- space-around`沿着主轴居中、分散排列,即将宽度或者高度均分为子控件数量的小块,在每个小块内,居中展示子控件。
space-between
、space-evenly
类似space-around
,但是展示方式略有不同。下面图片的顺序分别是space-around
->space-between
->space-evenly
,主轴为x轴(flexDirection:'row'
)
Align Items
在component
的style
属性中添加alignItems
属性是确定子控件在坐标轴副轴上的展示关系,主要属性有flex-start``center``flex-end
和streth
。- 需要注意的是,设置
streth
属性,需要保证副轴上的尺寸不允许有具体数值,否则不会有效果 flex-start``center``flex-end
这三个属性值与justifyContent
使用方式一致,只不过作用轴相反。
- 需要注意的是,设置
下图分别是flexDirection
、justifyContent
和alignItems
三个布局属性相互影响的结果。
布局代码如下(按照图片中布局顺序)
主轴是x轴,即按照水平排列子控件,受到属性justifyContent
的值的影响;副轴是y轴,受到属性alignItems
的值的影响。
<View style={{
height:100,
flexDirection:'row',
justifyContent:'flex-end',
alignItems:'flex-end',
backgroundColor:'#878787'
}}>
<View style={{
height:100,
flexDirection:'row',
justifyContent:'flex-start',
alignItems:'flex-end',
backgroundColor:'#878787'
}}>
<View style={{
height:100,
flexDirection:'row',
justifyContent:'center',
alignItems:'flex-start',
backgroundColor:'#878787'
}}>
stretch
属性值表示拉伸的意思,即在副轴方向上根据父控件在副轴上的尺寸对子控件进行拉伸。
- AlignSelf
在子component
的style
属性中添加alignSelf
属性可以覆盖父控件的style
中的alignItems
在当前控件上的作用效果,即重新确定当前的控件在父控件中副轴上的位置。
布局代码如下
<View style={{
height:100,
flexDirection:'row',
justifyContent:'flex-end',
alignItems:'flex-end',
backgroundColor:'#878787'
}}>
<View style={[styles.hw50,{backgroundColor:'#0bffd3'},{alignSelf:'center'}]}/>
<View style={[styles.hw50,{backgroundColor:'powderblue'},{alignSelf:'flex-start'}]}/>
<View style={[styles.hw50,{backgroundColor:'skyblue'}]}/>
<View style={[styles.hw50,{backgroundColor:'steelblue'}]}/>
</View>
padding
paddingLeft
paddingTop
paddingRight
paddingBottom
,值都是number
类型,类比 Android 中的padding
paddingLeft
paddingTop
paddingRight
paddingBottom
。margin
marginLeft
marginTop
marginRight
marginBottom
同上,类比 Android 中的相关属性及用法。