(本节包括React Native介绍、特点分析、环境搭建、RN文件结构、View组件讲解、FlexBox布局及props与state)
RN是React native的简称。在2015年的3月26日,Facebook公司正式发布了这一套框架,使用React框架跨平台开发原生移动应用的开源技术框架。有了跨平台这个特性,开发者可以使用React native高效的在Android和iOS开发应用程序。毕竟人家的标语就叫做Learn once,write anywhere。react native也因此在github上名燥一时。使用RN开发,可以让你既拥有native的良好人机交互体验,又保留了React框架的开发效率。(像人机交互体验很多都体现在用户触摸屏幕的时候,比如说长按屏幕的时候部分出现动画效果,手机的震动效果等)
学习RN的必要性:
1、混合开发:RN可以让开发者在RN擅长的领域使用RN语法开发,而在RN不方便实现的领域或者说以有原生代码实现好的领域直接使用原生代码。(有同学可能不太理解混合开发这个概念,这里老师就详细讲解一下。混合开发可以分为下面3种情况)
2、高效开发:使用RN开发,绝大部分UI界面和业务逻辑都是一套代码,并且使用RN比移动应用开发UI界面更高效。因为它有独特的UI框架和组件化开发可以使代码结构更清晰、可移植性可以更高。并且它可以自动适配不同的手机屏幕。正是因为这些功能,才让RN有了高效开发的特性。 3、热更新:当我们使用原生开发的时候,需要去提醒用户去应用市场下载新版本的做法显得特别繁琐。但是用RN开发的应用,开发者都可以在用户无感知的情况下加入新的界面。并且这种热更新行为是苹果官方允许的。(我知道,最近大家都在争论苹果禁用热更新的这一观点,但是其实苹果只是禁用了含有pl-patch和rollout这两个框架的应用哦。所以大家不需要担心RN热更新的问题哦。)
4、学习门槛低。我们使用的是JSX来开发,其实大家可以在代码中看到就是JS,大家在很短的时间内就可以熟悉它的语法。
相对于原生开发,RN内存消耗略大、运行速度略慢、组件并不是完全齐全,遇到某些问题还是需要原生开发都是它的缺陷。但相比其他跨平台开发方式来说,RN的性能相对来说已经好了很多。
React Native中文网,是开发者学习RN一个至关重要的平台。首页左上方显示的版本号,代表目前RN的最新版本。主版本号表示向下做了不兼容的API修改,次版本号表示做了向下兼容的功能性新增,修订号代表的是向下兼容的问题修正。
sudo chown -R
whoami/usr/local
。sudo chown 777 /usr/local
(在linux系统中有r w x三个权限,分别代表可读、可写、可执行。三个7代表所有用户都拥有对它进行读写和执行的权限)。$csrutil disable
关闭rootless
如果要打开的话,直接输入 enable就可以了brew uninstall node
。如果不记得自己安装过什么工具:在/usr/local/Cellar目录下有。/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"
import React,{Component}from 'react';
import表示引入外部文件。这句话的意思表示引入React框架中的Component组件。
import {
AppRegistry, //注册
StyleSheet, //样式
Text, //文本组件
View //视图组件
}from 'react-native';
这段代码表示引入react native中的组件。在rn中要运用到这些组件就必须要引入。如果打开项目的简介会发现有三百多兆,这是因为在node_modules文件夹中包含了所有的react-native的组件。
export default class Demo extends Component {
render() {}
}
这段代码表示注册一个类继承自Component。创建出来的这个类可以当做组件使用。里面的render方法就是渲染方法。这个方法将会返回要显示的第一层组件。
const myStyle = StyleSheet.create({
});
这段代码表示设置样式。与css的样式类似。
http://www.jianshu.com/p/4a82363f57aa
FlexBox学名为伸缩性弹性盒子布局。是W3C机构为了更方便对盒子布局进行伸缩布局而编写的。它可以改变大小以适应可用空间,当可用空间变大,flex元素将伸展大小以填充可用空间。反之,它则会自动缩小。
在web环境中,我们通常使用分离的样式表文件,那么在这些传统的样式设计的使用上可能会产生各种问题,比如说CSS规则和类名都在全局作用域里,如果不注意,一个组件的样式可能会影响到其他的组件。但是RN采用的是不同的方式,它采用基于javaScript的样式对象来代替传统样式表。那么现在我们就来创建并操作样式。
<Text style={{fontStyle:”italic"}}>哈哈哈哈</Text>
var fontStyle = {backgroundColor:'orange'};//创建对象
<Text style={fontStyle}>我是一个文字组件</Text>
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
}
}
一款好的APP离不开一个漂亮的布局。正如一见钟情,钟的还不脸么?所以面子工程不可谓不重要。而flexBox布局,正是为组件提供了一种在不同尺寸的设备上都能保持一致的布局属性。
宽和高决定了组件在屏幕上的尺寸,也就是大小。它们有一个像素无关的特性,也就是说在RN中尺寸是没有单位,它代表了设备的独立像素。
<View style={{width:100,height:100,backgroundColor:'pink',marginTop:20}}>
<Text style={{fontSize:16,margin:20}}>尺寸</Text>
</View>
上面的代码在iOS中尺寸单位被解释成了pt,这些单位确保了布局在任何不同的dpi的手机屏幕上显示都不会发生改变。
主轴:就是水平方向的轴线,可以理解为横轴。 侧轴:垂直于主轴,可以理解为竖轴。 但是这只是在默认状态下,而主轴和侧轴的方向是可以根据属性的值而发生改变的。
//创建几个text组件用于展示效果
export default class Demo extends Component{
render(){
return (
<View style={myStyle.container}>
<Text>哈哈哈哈</Text>
<Text>哈哈哈哈</Text>
</View>
);
}
}
// 此处是样式的代码
container: {
flex:1,
flexDirection:'column-reverse',
backgroundColor: 'yellow',
},
//多设置几行文字并添加颜色属性
<Text style={{backgroundColor:'red'}}>哈哈哈哈1</Text>
<Text style={{backgroundColor:'blue'}}>呼呼哈哈2</Text>
<Text style={{backgroundColor:'yellow'}}>哈哈哈哈3</Text>
<Text style={{backgroundColor:’pink’}}>哈哈哈哈4</Text>
//让主轴横向发展。删除flex=1,则可以横向布局
const myStyles = StyleSheet.create({
container: {
flexDirection:'row',
backgroundColor: ‘orange',
marginTop:40
},
而后依次设置justifyContent的值。
justifyContent:’space-around',
//给text设置高度
<Text style={{backgroundColor:’red',height:30}}>哈哈</Text>
<Text style={{backgroundColor:'blue',height:40}}>呼2</Text>
//设置alignItems
//stretch代表拉长对齐 表示若没有设高度或者高度为auto,子控件就会占满父控件
alignItems:’ stretch’
export default class Test2 extends Component{
render(){
return(
<View style={styles.container}
//设置超过屏幕宽度
<Text width = '200'>哈哈哈1</Text>
<Text width = '200'>哈哈哈2</Text>
></View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection:’row', //主轴方向
backgroundColor:'grey',
marginTop:25, //上边距
justifyContent:’flex-start‘, //主轴对齐方式
alignItems:’center’,//设置侧轴的对齐方式
},
});
//给每个Text添加高度.
接下来我想让第一个与父组件的顶部对齐。其他的都是居中显示的
<Text style={{backgroundColor:’red',flex:1,height:30,alignSelf:'flex-start'}}>哈哈</Text>
<Text style={{backgroundColor:'red',flex:1}}>哈哈</Text>
<Text style={{backgroundColor:'blue',flex:2}}>呼2</Text>
<Text style={{backgroundColor:'yellow',flex:2}}>哈哈3</Text>
<Text style={{backgroundColor:’pink’,flex:1}}>哈4</Text>
props是一个属性,代表属性的意思。可以从外界传入,也可以由自身给出。而且一经指定,在被指定的组件的生命周期中则不再改变。 也就是说它是只读的。
//本类定义属性的写法 要加上static
static defaultProps = {
name:'小红'
}
可以使用propTypes对属性进行检查。PropTypes是React的子类,使用它必须要将它导入。
import React, {Component,PropTypes} from 'react';
static propTypes = {
name:PropTypes.string, //表示name属性必须是string类型的
}
如果要求某个属性是必须传递的,则要在后面加上isRequired。
static propTypes = {
sex:PropTypes.string.isRequired, //设置了isRequired则这个属性的值必须从外界传递进来。
}
这里再介绍一个es6的知识点。延展操作符。当你有很多属性的时候,可以用一个延展操作符将这些属性都括起来。带到使用的时候,只需要打三个点取出。
var params = {name:'嘻嘻',age:18,sex:'男'}
//PropsTest是上一个界面
<PropsTest
{...params}
/>
当然,我们也可以只取出延展操作符的部分属性。我们称之为解构赋值。
var params = {name:'嘻嘻',age:18,sex:'男'}
var {name,sex} = params; //取出部分属性
<PropsTest
name = {name} //将属性值传出去
sex = {sex}
/>
再来看state,它代表状态的意思。对于需要改变的数据,我们需要使用state。当然它只能是在内部赋值,而不能接受从外界传入的值。在这里每个组件都有一个系统的setState方法用来改变状态,并且它是会刷新界面的哟~那么它在刷新界面的时候其实调用的就是Render函数。在这里跟大家先声明一下,因为render函数是一个异步函数,所以在render函数里面用setState去设置值,它是不会立即刷新的。 它可以保证同时刷新多个setState方法。
export default class Test extends Component {
state = { //创建state有两种方式
title:'默认值'
}
render (
<View style={styles.container}>
<Text>{this.state.title}</Text>
</View>
);
}
为了更清楚的阐述这个状态机,这里准备了一个小的案例。 写一个文本框和一个文字组件。当文本框内容发生变化的时候,触发一个回调函数,然后在回调函数中取出文本框的text值然后赋给下面的Text组件。 首先要使用文本框就要导入TextInput组件。
import {
AppRegistry,
StyleSheet,
Text,
View,
TextInput, //导入文本框
} from 'react-native';
写一个构造函数。其实每一个组件都可以有一个构造函数。它的第一条语句是固定的。当组件被初始化时,该函数将会被执行。通常在这个函数声明需要用的状态机变量。现在要做的就是在这里输入文字。
//构造函数
constructor(props){
super(props);
// 初始状态
this.state = {textInputValue:'请输入文字'};
}
当开发者需要改变状态机变量的值时,一定要使用this.setState函数。 我们通过提供一个方法,用来设置新值。
//用来设置新值
updateTextInputValue(newText) {
//this.setState将状态机设置成一个新的值
this.setState({textInputValue:newText});
}
render() {
return (
<View style={styles.container}>
<TextInput style={styles.textInputStyle}
placeholder={'请输入文字'}
onChangeText={(newText)=>this.updateTextInputValue(newText)}
>
</TextInput>
<Text style={styles.textShow}>
{this.state.textInputValue}
</Text>
</View>
);
}
}
上面代码中的调用的方法可以简写成onChangeText = {this.updateTextInputValue}。这种写法我们没办法看到newText的传递过程,但是它还是被传递了的。
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
//设置文本框的样式
textInputStyle: {
width:300,
height:150,
borderWidth:1,
borderStyle:'dashed',
margin:10
},
textShow: {
width:200,
height:30,
backgroundColor:'blue',
}
});
状态机变量value的默认值为:’请在这里输入文字’,当我们修改textarea里面的值时,就会触发updateText函数(PS:给onChangeText赋值时最好用箭头函数,不要写成onChangeText={this.handleChange}),在handleChange函数里面改通过this.state将textarea里面的值赋给状态机变量value。当状态机变量的值发生变化时,就会重新调用render函数进行UI渲染。状态机变量的值只要发生变化就会调用render函数重新渲染一次。