cd AwesomeProject
react-native run-ios
ps:可以使用--version
参数(注意是两
个杠)创建指定版本的项目。例如react-native init MyApp --version 0.44.3。
0.45及以上版本需要下载boost库编译 —》查看
http://bbs.reactnative.cn/topic/4301/ios-rn-0-45%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%89%80%E9%9C%80%E7%9A%84%E7%AC%AC%E4%B8%89%E6%96%B9%E7%BC%96%E8%AF%91%E5%BA%93-boost%E7%AD%89
在模拟器中,commond+R是重新加载
属性(props)的使用
//自定义的控件
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> ); } }
props
是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变
对于需要改变的数据,我们需要使用state
一般在 constructor中初始化 state,在需要修改时调用setState
方法
组件的生命周期。
组件的生命周期分成三个状态:
Mounting:已插入真实 DOM
Updating:正在被重新渲染
Unmounting:已移出真实 DOM
React 为每个状态都提供了两种处理函数,will函数在进入状态之前调用,did函数在进入状态之后调用,三种状态共计五种处理函数。
componentWillMount():只会在装载之前调用一次,在 render之前调用,你可以在这个方法里面调用setState改变状态,并且不会导致额外调用一次 render
componentDidMount():只会在装载完成之后调用一次,在 render之后调用,从这里开始可以通过ReactDOM.findDOMNode(this)获取到组件的 DOM 节点。
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount():卸载组件触发
此外,React还提供两种特殊状态的处理函数。
componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
特别注意:以下这些方法不会在首次 render组件的周期调用
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
创建组件实例并插入DOM时,会调用:
constructor()
//初始化 state 的位置,如果不需要初始化 state 并且不绑定方法的话,则不用实现该构造函数,注意state
不会随着任何props更新而更新,所以不要这样写:- constructor(props) {
- super(props); this.state = { color: props.initialColor }; }
render() //
在调用时,应该检查this.props
和this.state
,并返回一个作出反应的元素。此元素可以是本机DOM组件的表示形式,也可以是<div />
您自己定义的另一个复合组件。您也可以返回
null
或false
指示您不想要任何呈现。当返回null
或者false
,ReactDOM.findDOMNode(this)
将返回null
如果
shouldComponentUpdate()
返回false,则render()不会被调用componentDidMount()
this.setState
一般不会触发该方法
componentWillUpdate()
,render()
和componentDidUpdate()
将不会被调用,所以可以通过比较this.props
与nextProps
和this.state与
nextState来告诉组件跳过更新。
shouldComponentUpdate()返回 false 的时候,这个方法不会被调用。
每个组件还提供了一些其他API:
prevState
是对以前状态的引用。不应该直接改变它,而是应该根据prevState
和props构建一个新对象来表示更改。例如,
假设我们想增加一个状态值props.state
:
this.setState((prevState, props) => {
return {counter: prevState.counter + props.step};
});
第二个参数是一个可选的回调函数,官方建议用componentDidUpdate代替它的使用。
如果下一个 state 仅依赖上一个 state,官方建议如下形式使用:
this.setState((prevState) => {
return {counter: prevState.quantity + 1};});
类属性
如果props.color
没有提供,它将默认设置为'blue'
:
render() {
return <CustomButton /> ; // props.color will be set to blue
}
如果props.color
设置为null,它将保持为空:
render() {
return <CustomButton color={null} /> ; // props.color will remain null
}
实例属性
弹性(Flex)宽高
在组件样式中使用flex
可以使其在可利用的空间中动态地扩张或收缩。一般而言我们会使用flex:1
来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1
,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的flex
值不一样,则谁的值更大,谁占据剩余空间的比例就更大(即占据剩余空间的比等于并列组件间flex
值的比)。
ps: flexDirection标签控制 flex 拉伸方向(控制主轴方向),默认是column竖直轴(默认拉伸高度),可以设置成水平轴(row
)
justifyContent标签可以控制子组件的排列顺序,分别是:
flex-start:
主轴首部
center:主轴中部
flex-end:主轴尾部
space-around:组件在主轴方向按固定间距排列(比如每个组件都是左右间距50或者每个组件上下间距都是50)
space-between:主轴方向等间距排列。
Align Items
在组件的style中指定alignItems
可以决定其子元素沿着次轴
对应的这些可选项有:flex-start
、center
、flex-end
以及stretch
。
注意:要使stretch
选项生效的话,子元素在次轴方向上不能有固定的尺寸
style 賦值
e.g.:
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', }, });
后声明的属性会覆盖先声明的同名属性(上面的例子是覆蓋了 color 這個屬性)
所以文本的風格是(:紅藍、大紅、大藍、大
Textinput
从TextInput里取值这就是目前唯一的做法:订阅它的onChangeText
事件来读取用户的输入,即使用onChangeText
写入state,然后从this.state中取出值
TextInput
在安卓上默认有一个底边框,同时会有一些padding。如果要想使其看起来和iOS上尽量一致,则需要设置padding: 0
,同时设置underlineColorAndroid="transparent"
来去掉底边框。又,在安卓上如果设置
multiline = {true}
,文本默认会垂直居中,可设置textAlignVertical: 'top'
样式来使其居顶显示。又又,在安卓上长按选择文本会导致
windowSoftInputMode
设置变为adjustResize
,这样可能导致绝对定位的元素被键盘给顶起来。要解决这一问题你需要在AndroidManifest.xml中明确指定合适的windowSoftInputMode
( https://developer.android.com/guide/topics/manifest/activity-element.html )值,或是自己监听事件来处理布局变化
长列表(listview):FlatList或是SectionList。
FlatList:没有组视图
const myListData = [ {key: 'Devin'}, {key: 'Jackson'}, {key: 'James'}, {key: 'Joel'}, {key: 'John'}, {key: 'Jillian'}, {key: 'Jimmy'}, {key: 'Julie'}, ]; export default class MyListViewDemo extends Component<{}> { render() { return ( <View style = {styles.container}> <FlatList data = {myListData} renderItem = { ({item}) => <View style = {styles.flesone}> <Image source = {require('./image/test.png')} style = {{alignItems: 'center'}}/> <Text style = {styles.item} >{item.key}</Text> </View> } /> </View> ); } }
SectionList:有组视图const sectionListData = [ {title: {name: 'Jo', age: 20}, data: [ {key: 'Devin'}, {key: 'Jackson'}, {key: 'James'}, {key: 'Joel'}, {key: 'John'}, {key: 'Jillian'}, {key: 'Jimmy'}, {key: 'Julie'}, ]}, {title: {name: 'XYF', age: 30}, data: [ {key: 'XYF_SSS'}, {key: 'XYF_Jackson'}, {key: 'XYF_James'}, {key: 'XYF_Joel'}, ]}, ]; export default class MySectionListDemo extends Component<{}> { render() { return ( <View style = {styles.flexone}> <SectionList sections = {sectionListData} renderItem = {({item}) => <Text style = {{color: 'red', fontSize: 20}}> {item.key} </Text> } renderSectionHeader = {({section}) => <Text style = {{fontSize: 30, marginLeft: 100}}> {section.title.name} </Text>} /> </View> ); } }导航栏:目前主推react-navigation
只针对iOS平台开发,并且想和系统原生外观一致,那么可以选择
NavigatorIOS
e.g.:
//只有声明了
{ navigation }的才能继续跳转。
const HomeScreen = ({ navigation }) => ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Home Screen</Text> <Button onPress={() =>
navigation.navigate('Details’) //跳转到” Details"界面}
title="Go to details" /> </View> ); const DetailsScreen = () => ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Details Screen</Text> </View> ); //初始化
StackNavigator,注册导航栏所在的窗口视图
const RootNavigator = StackNavigator({ Home: { screen: HomeScreen, navigationOptions: {
//导航栏标题 headerTitle: 'Home', }, }, Details: { screen: DetailsScreen, navigationOptions: {
//导航栏标题 headerTitle: 'Details', }, }, }); export default class MainScreen extends Component<{}> { render() { return ( <RootNavigator /> ); } }
工具栏:
class App extends Component<{}> { render() { return ( <View style={styles.container}> <Text style={styles.welcome}> Welcome to React Native! </Text> <Text style={styles.instructions}> To get started, edit App.js </Text> <Text style={styles.instructions}> {instructions} </Text> </View> ); } } /*标签栏 tabbar 的简单使用*/ class MyTabBarItem extends Component<{}> { render(){ var icon = this.props.active ? this.props.selectImage : this.props.normalImage; return ( <Image source={icon} style={{tintColor: this.props.tintColor, width: 25, height: 25}}/> ); } } const SimpleApp = TabNavigator({ Home: { screen: App, navigationOptions: ({navigation}) => ({ tabBarVisible: true, tabBarLabel: '首页', tabBarIcon: ({focused, tintColor})=>( <MyTabBarItem tintColor={tintColor} focused={focused} selectImage= {require('./image/test.png')} normalImage={require('./image/test.png')} /> ), }) }, Detail: { screen: App, navigationOptions: ({navigation}) => ({ tabBarLabel: '消息', tabBarIcon: ({focused, tintColor})=>( <MyTabBarItem tintColor={tintColor} selectImage= {require('./image/test.png')} normalImage={require('./image/test.png')} /> ), }) }, Three: { screen: App, navigationOptions: ({navigation}) => ({ tabBarLabel: '我的', tabBarIcon: ({focused, tintColor})=>( <MyTabBarItem tintColor={tintColor} focused={focused} selectImage= {require('./image/test.png')} normalImage={require('./image/test.png')} /> ), }) } },{ tabBarPosition:'bottom', swipeEnabled:false, animationEnabled:false, lazy:true, tabBarOptions:{ activeTintColor:'red', inactiveTintColor:'black', style:{backgroundColor:'#fff',}, labelStyle: { fontSize: 16, // 文字大小 }, } }) export default class MyTabbar extends Component<{}> { render () { return ( <SimpleApp/> ); } }
常用属性:
screen:和导航的功能是一样的,对应界面名称,可以在其他页面通过这个screen传值和跳转。 navigationOptions:配置TabNavigator的一些属性 { title:标题,会同时设置导航条和标签栏的title tabBarVisible:是否隐藏标签栏。默认不隐藏(true) tabBarIcon:设置标签栏的图标。需要给每个都设置 tabBarLabel:设置标签栏的title。推荐 } tabBarPosition:设置tabbar的位置,iOS默认在底部,安卓默认在顶部。(属性值:'top','bottom') swipeEnabled:是否允许在标签之间进行滑动 animationEnabled:是否在更改标签时显示动画 lazy:是否根据需要懒惰呈现标签,而不是提前,意思是在app打开的时候将底部标签栏全部加载,默认false,推荐为true trueinitialRouteName: 设置默认的页面组件 backBehavior:按 back 键是否跳转到第一个Tab(首页), none 为不跳转 tabBarOptions:配置标签栏的一些属性iOS属性 activeTintColor:label和icon的前景色 活跃状态下 activeBackgroundColor:label和icon的背景色 活跃状态下 inactiveTintColor:label和icon的前景色 不活跃状态下 inactiveBackgroundColor:label和icon的背景色 不活跃状态下 showLabel:是否显示label,默认开启 style:tabbar的样式 labelStyle:label的样式安卓属性 activeTintColor:label和icon的前景色 活跃状态下 inactiveTintColor:label和icon的前景色 不活跃状态下 showIcon:是否显示图标,默认关闭 showLabel:是否显示label,默认开启 style:tabbar的样式 labelStyle:label的样式 upperCaseLabel:是否使标签大写,默认为true pressColor:material涟漪效果的颜色(安卓版本需要大于5.0) pressOpacity:按压标签的透明度变化(安卓版本需要小于5.0) scrollEnabled:是否启用可滚动选项卡 tabStyle:tab的样式 indicatorStyle:标签指示器的样式对象(选项卡底部的行)。安卓底部会多出一条线,可以将height设置为0来暂时解决这个问题 labelStyle:label的样式 iconStyle:图标样式
还有DrawerNavigator(抽屉视图/侧栏视图),参考下面详情
详细参考:https://reactnavigation.org/docs/intro/quick-start
属性(个别需要特别注意的)
keyboardType enum("default", 'numeric', 'email-address', "ascii-capable", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search')
决定弹出的何种软键盘的,譬如
numeric
(纯数字键盘)。这些值在所有平台都可用:
- default
- numeric
- email-address
- phone-pad
returnKeyType enum('done', 'go', 'next', 'search', 'send', 'none', 'previous', 'default', 'emergency-call', 'google', 'join', 'route', 'yahoo')
决定“确定”按钮显示的内容。在Android上你还可以使用
returnKeyLabel
来自定义文本。跨平台
下列这些选项是跨平台可用的:
done
go
next
search
send
限Android
下列这些选项仅限Android使用:
none
previous
限iOS
下列这些选项仅限iOS使用:
default
emergency-call
join
route
yahoo
加载图片
http://reactnative.cn/docs/0.49/images.html
ps: 在iOS上,每次调整Image组件的宽度或者高度,都需要重新裁剪和缩放原始图片。这个操作开销会非常大,尤其是大的图片。比起直接修改尺寸,更好的方案是使用transform: [{scale}]
的样式属性来改变尺寸。比如当你点击一个图片,要将它放大到全屏的时候,就可以使用这个属性
resizeMode的属性:cover(默认),contain(全部展示图片,自动缩放)、stretch(拉伸图片,让宽或者高占满控件)
设置背景色为透明色: backgroundColor: ‘transparent’
各种颜色参数:http://reactnative.cn/docs/0.49/colors.html#content
可点击/长按的组件(点击效果按钮)
一般来说,你可以使用TouchableHighlight来制作按钮或者链接。注意此组件的背景会在用户手指按下时变暗。
在Android上还可以使用TouchableNativeFeedback,它会在用户手指按下时形成类似墨水涟漪的视觉效果。
TouchableOpacity会在用户手指按下时降低按钮的透明度,而不会改变背景的颜色。
如果你想在处理点击事件的同时不显示任何视觉反馈,则需要使用TouchableWithoutFeedback。
e.g.:
<TouchableHighlight onPress = {() => Alert.alert("测试单击”)}
onLongPress = {() => Alert.alert("这是长按效果")}>
<Text>My Test </Text> </TouchableHighlight>
定时器使用
需要注意的是铭记在unmount组件时清除(clearTimeout/clearInterval)所有用到的定时器
直接操作组件setNativeProps的简单使用:http://reactnative.cn/docs/0.49/direct-manipulation.html#content
各种性能影响比如:ListView初始化渲染太慢以及列表过长时滚动性能太差,滑动画面卡顿等的解决方法:http://reactnative.cn/docs/0.49/performance.html#content
升级教程:http://reactnative.cn/docs/0.49/upgrading.html#content
特定平台代码的区分:http://reactnative.cn/docs/0.49/platform-specific-code.html#content
React Native会检测某个文件是否具有
.ios.
或是.android.
的扩展名,然后根据当前运行的平台加载正确对应的文件。假设你的项目中有如下两个文件:
BigButton.ios.js BigButton.android.js
这样命名组件后你就可以在其他组件中直接引用,而无需关心当前运行的平台是哪个。
import BigButton from './components/BigButton';
React Native会根据运行平台的不同引入正确对应的组件。
实用的方法是Platform.select()
e.g.:
import { Platform, StyleSheet } from 'react-native'; var styles = StyleSheet.create({ container: { flex: 1, ...Platform.select({ ios: { backgroundColor: 'red', }, android: { backgroundColor: 'blue', }, }), }, });
上面的代码会根据平台的不同返回不同的container样式——iOS上背景色为红色,而android为蓝色。
这一方法可以接受任何合法类型的参数,因此你也可以直接用它针对不同平台返回不同的组件,像下面这样:
var Component = Platform.select({ ios: () => require('ComponentIOS'), android: () => require('ComponentAndroid'), })(); <Component />;
对于其他文件组件的引用:
//App.js 文件
import CustTabBarItem from "./TabBarItem” //App 文件和 TabBarItem.js在同一目录下
…..
//使用
<CustTabBarItem tintColor={tintColor} focused={focused} selectImage={{uri: 'tabbar_home_select'}} normalImage={{uri: 'tabbar_home'}} />
…..
//TabBarItem.js 文件
export default class TabBarItem extends Component { render(){ return ( <Image source={this.props.focused ? this.props.selectImage : this.props.normalImage} style={{tintColor: this.props.tintColor, width: 25, height: 25}}/> ); } }