一个最简单的HelloWorld页面
先不多解释,直接上代码:
import React, { Component } from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';
export default class helloworldComponent extends Component
{
render()
{
return (
<View style={styles.container}>
<Text style={styles.welcome}>Hello World!</Text>
</View>
);
}
}
const styles = StyleSheet.create(
{
container:
{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome:
{
fontSize: 20,
textAlign: 'center',
margin: 10,
}
});
// 这句话就相当于Java里面的main函数,不用特别深入了解,知道即可
// 第一个参数的'helloworld'必须跟你的项目名一样
AppRegistry.registerComponent('helloworld', () => helloworldComponent);
官方推荐使用ES6语法,不熟悉ES6的同学可能看起来感觉这完全不是JS代码,可以先看看这篇文章熟悉一下区别:
react-react-native-的es5-es6写法对照表
对于Android平台而言,index.android.js
就是整个项目的入口,AppRegistry.registerComponent
则是入口中的main函数。我一般习惯index.android.js
中只简单的写两三行代码,其它的以组件的形式加载进来:
import React, { Component } from 'react';
import { AppRegistry } from 'react-native';
import MainPage from './views/MainPage';
// 注意,这里用引号括起来的'helloworld'必须和你init创建的项目名一致
AppRegistry.registerComponent('helloworld', () => MainPage);
JSX语法
有React.js
基础的话可能会很熟悉这个,我在学习ReactNative
的时候没有接触过React.js
,所以有些吃亏。
JSX
可以看做是内嵌在JS中的一段xml代码,不需要引号包裹,放在这个里面:render(){ return (JSX);}
,{}
表示里面是一个变量或者表达式,和jsp的${}
类似。
注意每个render里面返回的XML根节点只能是一个,像下面这样的写法是错误的:
render()
{
return (
<Text>Hello World!</Text>
<Text>Hello World!</Text>
);
}
只能另外用一个组件把它包裹,比如<View>
:
render()
{
return (
<View>
<Text>Hello World!</Text>
<Text>Hello World!</Text>
</View>
);
}
动态拼接JSX
因为JSX不是普通的字符串,我们没法像拼接字符串一样拼接它,但还是有办法的。JSX里面可以随意内嵌表达式:
class TestComponent extends Component
{
constructor(props)
{
super(props);
this.list = ['张三', '李四', '王二麻子', '小茗同学'];
}
render()
{
return (
<View style={{flex:1}}>
<Text>你好啊</Text>
{this.list.map((item, idx) => <Text key={'idx_'+idx}>{item}</Text>)}
<Image source={require('./image/logo.png')}/>
</View>
);
}
}
再复杂一点的还可以层层嵌套,代码多了则可以把遍历的代码单独写到一个方法里面然后调用,比如:
class TestComponent extends Component
{
constructor(props)
{
super(props);
this.list = ['张三', '李四', '王二麻子', '小茗同学'];
}
renderList(list)
{
return list.map((item, idx) =>
{
return (<Text key={'idx_'+idx}>{item}</Text>);
});
}
render()
{
return (
<View style={{flex:1}}>
<Text>你好啊</Text>
{this.renderList(this.list)}
<Image source={require('./image/logo.png')}/>
</View>
);
}
}
样式篇
样式的写法
样式可以直接写在style上面:
<Text style={{color: 'red', fontSize: 16}} />
也可以像css一样先单独定义好再引用,不过和css还是有很大差别的:
var styles = StyleSheet.create({
btn: {
width: 38,
height: 38,
},
background: {
backgroundColor: '#222222',
},
active: {
borderWidth: 2,
borderColor: '#00ff00',
}
});
然后这样写:
<Text style={styles.btn} /> // 单个class
<Text style={[styles.btn, styles.active]} /> // 多个class
<Text style={[styles.btn, {color: 'red'}]} /> // class与style混写
注意事项:
- 样式写法采用的是JSON格式;
- 字符串属性必须加引号;
- 大小全部没有px,纯数字;
- 采用驼峰式命名,不是中划线;
直接操作某个元素
可以使用ref
给元素实现类似HTML中的id的效果,即this.refs[id]
与document.getElementById(id)
类似:
render()
{
return (
<View ref="btn" style={{width: 100, height: 100}}/>
);
}
componentDidMount()
{
// 组件显示完毕给它设置红色边框效果
this.refs['btn'].setNativeProps
({
style: {borderColor: 'red', borderWidth: 5}
});
}
当然,一般推荐使用state
来修改界面,除非你对性能特别关注才用上述方法。
已知setNativeProps
无法修改Image
的source
,这应该是个bug。
图片加载
加载本地图片
官网推荐使用require加载图片,路径就是相对于js的相对路径,这种方式可以自动设置宽高度:
<Image source={require('./images/check.png')} />
虽然这种方式有很多优点,但是带来了一个致命的缺点:就是图片路径无法动态指定,比如下面这个例子,如果有100种状态需要判断,难道要写100个if else
?
// 正确
<Image source={require('./my-icon.png')} />
// 错误
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />
// 正确
var icon = this.props.active ? require('./my-icon-active.png') : require('./my-icon-inactive.png');
<Image source={icon} />
目前还没有找到这个问题的有效解决方法。
加载app资源图片
加载已经打包到App中的图片资源(通过Xcode的asset类目或者Android的drawable文件夹打包):
假设有这样一个文件:android\app\src\main\res\drawable-hdpi\ic_launcher.png
,那么加载时可以直接这样,注意不需要.png
后缀,而且必须手动指定宽高度,否则默认是0*0
:
<Image source={{uri: 'ic_launcher'}} style={{width: 40, height: 40}} />
加载网络图片
加载网络图片和加载资源图片一样,也要手动指定宽高度:
<Image source={{uri: 'http://test.liuxianan.com/sample.jpg'}} style={{width: 40, height: 40}} />
组件的生命周期
附录:所有可用CSS列表
注意:部分属性安卓不支持,如shadow
。
RN中所有可用的CSS列表如下:
"alignItems",
"alignSelf",
"backfaceVisibility",
"backgroundColor",
"borderBottomColor",
"borderBottomLeftRadius",
"borderBottomRightRadius",
"borderBottomWidth",
"borderColor",
"borderLeftColor",
"borderLeftWidth",
"borderRadius",
"borderRightColor",
"borderRightWidth",
"borderStyle",
"borderTopColor",
"borderTopLeftRadius",
"borderTopRightRadius",
"borderTopWidth",
"borderWidth",
"bottom",
"color",
"flex",
"flexDirection",
"flexWrap",
"fontFamily",
"fontSize",
"fontStyle",
"fontWeight",
"height",
"justifyContent",
"left",
"letterSpacing",
"lineHeight",
"margin",
"marginBottom",
"marginHorizontal",
"marginLeft",
"marginRight",
"marginTop",
"marginVertical",
"opacity",
"overflow",
"padding",
"paddingBottom",
"paddingHorizontal",
"paddingLeft",
"paddingRight",
"paddingTop",
"paddingVertical",
"position",
"resizeMode",
"right",
"rotation",
"scaleX",
"scaleY",
"shadowColor",
"shadowOffset",
"shadowOpacity",
"shadowRadius",
"textAlign",
"textDecorationColor",
"textDecorationLine",
"textDecorationStyle",
"tintColor",
"top",
"transform",
"transformMatrix",
"translateX",
"translateY",
"width",
"writingDirection"