这两天看了下rn文档:https://facebook.github.io/react-native/docs/getting-started.html
做了初步的学习,这里记下一些入门部分的要点。
打怪升级开始--------------------------------------------------------
序:npmV5安装create-react-native-app会报错?
solution:是的,所以官方github上推荐npm切换到v3或v4,或用近期版本的yarn安装:
yarn global add create-react-native-app
create-react-native-app my-app
cd my-app
yarn start
1.ReactNative组件
rn提供的组件分6类:基础展示组件、交互组件、列表组件、针对IOS的组件、针对android的组件、其他组件。
初学者只需要认识前三种。
--基础组件,足以搭建基本的界面UI:
View(相当于div)、Text(相当于p)、Image(相当于img)、TextInput(相当于input)、ScrollView(设定高/宽度后,超出内容可以滚动显示)、StyleSheet(用于创建样式表对象以应用于组件上)
--交互组件,实现屏幕的点击和手势
Button(应付点击和长按事件,ios和android上样式不一致),RN还提供了自定义类Button交互组件的途径:
TouchableOpacity:用于包裹内容的组件,点击内容会变透明;
TouchableNativeFeedback(android only)
Picker(上下滑动选择器) Switch(开关按钮) Slider(类似音量调节的滑动条) //知道有这几个就行
--列表数据
FlatList:渲染同一类型的简单数据,且不在可视区的不会渲染
SectionList:和FlatList类似,可对数据分组(区),如电话簿按字母对联系人号码分类
2.样式
const styles = StyleSheet.create({
container: {
borderRadius: 4,
borderWidth: 0.5,
}
});
<View style={styles.container}>
<Text style={[styles.title, this.props.isActive && styles.activeTitle]} />
</View>
3.布局
RN提供了flexbox的方式实现app界面的布局,但flexbox与css有些区别:
1.flexDirection属性取值 column || row 且默认值为column(默认排列为竖直方向,基轴为竖直方向)
2.flex属性只接受一个整数作为值
3.justifyContent:flex-start || flex-end || center || space-around || space-between || space-evenly
4.alignItems:flex-start || flex-end || center || stretch (使用stretch时交叉轴方向不能定义长度)
另外,rn提供了Dimensions模块帮我们获取客户端尺寸:
var Dimensions = require('Dimensions');
var { width, height } = Dimensions.get('window');
4.图片
(1).引用项目源码中的图片
<Image source={require('./test.png')} />
编译时RN会以当前js文件为相对路径引用图片。另,如果有test.ios.png和test.android.png两张图,RN会根据平台自动获取对应的一张图。如果有test@2x.png和test@3x.png两张图,RN会根据设备自动获取适当精度的图片。
!注意1:source属性的require(url)里,url推荐使用静态字符串,如:
var icon = this.props.active
? require('./my-icon-active.png')
: require('./my-icon-inactive.png');
<Image source={icon} />; //不要用模板字符串或变量名构造动态url
!注意2:videos不能使用flex来伸缩,因为非图片资源的尺寸信息不会正确传到source属性中(A caveat is that videos must use absolute positioning instead of flexGrow
, since size info is not currently passed for non-image assets. )。如果直接链接到Xcode中或android的资源文件夹中,则没有这个缺陷。
(2).请求网络图片
<Image source={{uri: 'https://facebook.github.io/react/logo-og.png'}}
style={{width: 400, height: 400}} />
请求网络图片时候,需要设置尺寸样式
由于苹果的APP数据传输安全策略,最好使用https协议请求图片;如果图片来源在自己服务器上,可以通过添加白名单规避 add an App Transport Security exception
5.icon在RN中引入icon图标字体要用到插件react-native-vectoricons
6.网络请求
RN提供了fetch方式(也是RN推荐的方式)实现网络请求,fetch只是用promise来实现异步操作,RN里也可以使用async/await语法糖。这里fetch的使用和一般前端的使用一致,可参考MDN文档:
RN也实现了内置的XMLHttpRequest API,所以我们也可以直接写ajax,不过这里的ajax并没有实现浏览器的CORS.
RN也支持WebSocket.var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
// connection opened
ws.send('something'); // send a message
};
ws.onmessage = (e) => {
// a message was received
console.log(e.data);
};
ws.οnerrοr=fn
ws.onclose=fn
...
7.平台识别
RN提供了一个模块,帮助我们识别app所跑的平台是ios还是android:
(1).Platform模块:
//Platform.OS -- 直接识别平台
import {Platform, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
height: Platform.OS === 'ios' ? 200 : 100,
});
//Platform.select -- 选取样式
const styles = StyleSheet.create({
container: {
flex: 1,
...Platform.select({
ios: {
backgroundColor: 'red',
},
android: {
backgroundColor: 'blue',
},
}),
},
});
//Platform.select--选取组件
const Component = Platform.select({
ios: () => require('ComponentIOS'),
android: () => require('ComponentAndroid'),
})();
<Component />;
//Platform.Version -- android版本
if (Platform.Version === 25) {
console.log('Running on Nougat!');
}
//ios版本,.Version的结果是一个字符串,表示系统版本号
const majorVersionIOS = parseInt(Platform.Version, 10);
if (majorVersionIOS <= 9) {
console.log('Work around a change in behavior');
}
(2).组件扩展名检测
当有文件名为Button.ios.js 和 Button.android.js时,const BigButton = require('./BigButton');会直接引入适配平台的那个组件。
8.路由ReactNavigation
过了一遍react-navigation的官网文档,react-navigation是社区针对app常见使用场景开发维护的导航插件。主要提供两个方法:
StackNavigator
export default HomeScreen = StackNavigator({
HomeStack: { //用户自定义的路由名(视图名)
screen: HomeStack, //路由名的值是固定格式 {screen:组件名}
},
Modal:{screen: Modal}
},
{
mode: 'modal', //视图切入时的动画模式,默认自右向左,'modal'则自底向上
headerMode: 'none',
initialRouteName: 'HomeStack'
}
);
0.StackNavigator生成的路由组件内部实现了类browser的历史记录栈。
1.用JS对象语法的形式组织视图组件,StackNavigator方法接收两个参数,一个是路由配置对象,第二个可选的功能参数对象。该方法返回一个路由组件。
2.第一个对象参数的格式是固定的。{自定义路由名:{screen:路由对应的组件名screen component},...rest}
3.第二个对象参数可以指定初始时显示的视图、当前视图是否隐藏导航头部、视图进入时的动画模式等。
4.如何实现路由跳转?
当app中的组件通过StackNavigator组件起来后,可以通过StackNavigator传给screen component的navigation接口实现视图跳转:
<Button
onPress={()=>{this.props.navigation.navigate('Modal');}}
title="Info"
color="red"
/>
5.如何实现路由嵌套?
StackNavigator生成的路由组件可以作为另一个StackNavigator参数中的screen component:
const HomeStack = StackNavigator({
//...
);
export default HomeScreen = StackNavigator({
HomeStack: {
screen: HomeStack,
},
//...
},
{
initialRouteName: 'HomeStack',
}
);
在StackNavigator的路由树中可以通过navigation.navigate(routename)自由跳转。
6.APP中往往有底部的导航标签页,难道也用stacknavigator实现?
不是。react-navigation提供了另一个专门的方法TabNavigator。用法如StackNavigator.
7.路由跳转时候带参数?
8.react-navigation自带的头部太丑?
//单纯设置标题
在screen对应的组件,添加静态属性navigationOptions
static navigationOptions = {
title: 'Home',
};
//navigationOptions 也可以是一个函数使用参数
static navigationOptions = ({ navigation }) => {
const { params } = navigation.state;
return {
title: params ? params.otherParam : 'A Nested Details Screen',
}
};
//在该screen组件内更新navigationOptions参数
this.props.navigation.setParams({otherParam: 'Updated!'})
//修改头部样式
headerStyle:包裹头部的div
headerTintColor:返回按钮和标题的颜色
headerTitleStyle:标题样式
//在多个screens中使用通用navigationOptions
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
/* The header config from HomeScreen is now here */
navigationOptions: {
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
},
}
);
//navigationOptions优先级 覆盖
screen component中的navigationOptions会和顶层的StackNavigatior第二个参数的navagationOptions合并
//使用自定义的title
static navigationOptions = {
// headerTitle instead of title
headerTitle: <LogoTitle />,
};
headerTitle是专门针对StackNavigatior的属性,默认会展示一个Text组件显示title
//添加头部按钮
static navigationOptions = {
headerTitle: <LogoTitle />,
headerRight: (
<Button
onPress={() => alert('This is a button!')}
title="Info"
color="#fff"
/>
),
};
//通过头部按钮与screen 组件交互
1.static navigationOptions=()=>{params}
2.define method
3.WillMount : setParams
.Button onPress=()=>{param.method}
//修改返回键文本
A组件跳到B组件,在A组件的navigationOptions.headerBackTitle修改文本
//覆盖返回键
navigationOptions.headerLeft
9.想实现一个全局的模态框?
最外层navigator包含一个modal组件和一个stack组件,
在stack组件内部跳转到modal组件
最外层navigator的option参数添加mode:'modal',headerMode:'none'
TapNavigator
提供顶部或底部导航标签页实现:
const RootStack = TabNavigator({
Home: {
screen: HomeScreen,
},
//...
},
{
mode: 'modal',
headerMode: 'none',
initialRouteName: 'Home',
tabBarOptions: {
activeTintColor: 'tomato',
style:{backgroundColor:'#256545'}
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false,
}
);
//待续