React Native移动框架功能研究
此篇只研究React Native框架的功能。
一、React Natvie是什么
React Native是使用React(或者说JS)来开发原生APP的框架。
二、React Native的愿景
1.提供一直的跨平台开发原生APP的一直体验。
2.使用JS和React提高跨平台开发效率。
三、React Native提供的特性
1.提供了丰富的原生组件,可以是APP获得平台一致的视觉效果和体验,同时获得最佳的性能和流畅性。
// iOS & Android var React = require(‘react-native‘); var { ScrollView, TouchableHighlight, Text } = React; var TouchDemo = React.createClass({ render: function() { return ( <ScrollView> <TouchableHighlight onPress={() => console.log(‘pressed‘)}> <Text>Proper Touch Handling</Text> </TouchableHighlight> </ScrollView> ); }, });
2.JS代码和原生平台之间的所有操作都是异步执行的,原生模块可以根据需要自由创建线程。同时两者之间的通讯是完全可序列化的,这使其可以借助Chorme开发这工具进行调试。
3.提供强大的触控事件处理系统,可以在复杂的UI层次结构下方便的处理触控事件。
// iOS & Android var React = require(‘react-native‘); var { ScrollView, TouchableHighlight, Text } = React; var TouchDemo = React.createClass({ render: function() { return ( <ScrollView> <TouchableHighlight onPress={() => console.log(‘pressed‘)}> <Text>Proper Touch Handling</Text> </TouchableHighlight> </ScrollView> ); }, });
4.通过Flexbox简化UI布局,提供高性能机制声明样式和布局,并可直接应用到组件中。
// iOS & Android var React = require(‘react-native‘); var { Image, StyleSheet, Text, View } = React; var ReactNative = React.createClass({ render: function() { return ( <View style={styles.row}> <Image source={{uri: ‘http://facebook.github.io/react/img/logo_og.png‘}} style={styles.image} /> <View style={styles.text}> <Text style={styles.title}> React Native </Text> <Text style={styles.subtitle}> Build high quality mobile apps using React </Text> </View> </View> ); }, }); var styles = StyleSheet.create({ row: { flexDirection: ‘row‘, margin: 40 }, image: { width: 40, height: 40, marginRight: 10 }, text: { flex: 1, justifyContent: ‘center‘}, title: { fontSize: 11, fontWeight: ‘bold‘ }, subtitle: { fontSize: 10 }, });
5.提供灵活的机制,方便自定义原生视图和模块。四、React Native的功能1.样式React Native在JS中定义和引用样式。可以通过StyleSheet定义样式
var styles = StyleSheet.create({ base: { width: 38, height: 38, }, background: { backgroundColor: ‘#222222‘, }, active: { borderWidth: 2, borderColor: ‘#00ff00‘, }, });
在组件中使用样式
<Text style={styles.base} />
<View style={styles.background} />
同时可以接受多个样式,后边的会覆盖前边的样式
<View style={[styles.base, styles.background]} />
可以结合表达式控制是否应用样式
<View style={[styles.base, this.state.active && styles.active]} />
也可以直接在元素中声明样式,但是每次渲染都会重建样式,影响性能。
<View style={[styles.base, { width: this.state.width, height: this.state.width * this.state.aspectRatio }]} />
样式也可以作为参数传递
var List = React.createClass({ propTypes: { style: View.propTypes.style, elementStyle: View.propTypes.style, }, render: function() { return ( <View style={this.props.style}> {elements.map((element) => <View style={[styles.element, this.props.elementStyle]} /> )} </View> ); } }); // ... 在别的文件中引用List组件 ... <List style={styles.list} elementStyle={styles.listElement} />
2.图片加载本地静态图片,图片基于当前js的目录。如果带有平台相关的扩展名,则系统自动根据当前的系统平台自动加载相关的图片,例如my-icon.ios.png
<Image source={require(‘./my-icon.png‘)} />
使用@2x,@3x这样的文件名后缀,可以为不同的屏幕精度提供图片可以在ReactNative中直接使用内嵌到APP中的图片资源
<Image source={{uri: ‘app_icon‘}} style={{width: 40, height: 40}} />
可以加载网络图片,但是需要手动指定图片大小
<Image source={{uri: ‘https://facebook.github.io/react/img/logo_og.png‘}}
style={{width: 400, height: 400}} />
通过将元素嵌套到Image中实现背景图片
return ( <Image source={...}> <Text>Inside</Text> </Image> );
3.手势触控系统提供Touchable和TouchableHighlight来定义可触控控件。响应者的声明周期如下:是否愿意成为响应者View.props.onStartShouldSetResponder(开始触摸的时候是否愿意)View.props.onMoveShouldSetResponder(如果不是响应者,则每次开始移动触控点时询问是否原因)如果愿意成为响应者,则接下来开始尝试成为响应者View.props.onResponderGrant(成功成为响应者)View.props.onResponderReject(被拒绝成为响应者)如果成功成为响应者,则开始具体的响应触控事件View.props.onResponderMove(响应屏幕手指移动)View.props.onResponderRelease(响应屏幕手指离开)View.props.onResponderTerminationRequest(其他组件请求接替响应者,返回true则释放自己响应者角色)View.props.onResponderTerminate(响应者角色已交出)onStartShouldSetResponder与onMoveShouldSetResponder是以冒泡的形式调用的,即嵌套最深的节点最先调用。如果某个父View会希望能先成为响应者。我们可以利用“捕获期”来解决这一需求。View.props.onStartShouldSetResponderCaptureView.props.onMoveShouldSetResponderCapture4.动画用于全局的布局动画LayoutAnimation,和用于创建更精细的交互控制的动画Animated。Animated库使得开发者可以非常容易地实现各种各样的动画和交互方式,并且具备极高的性能。它包括两个值类型,Value用于单个的值,而ValueXY用于向量值;还包括三种动画类型,spring,decay,还有timing,以及三种组件类型,View,Text和Image。我们可以使用Animated.createAnimatedComponent方法来对其它类型的组件创建动画。
class Playground extends React.Component { constructor(props: any) { super(props); this.state = { bounceValue: new Animated.Value(0), }; } render(): ReactElement { return ( <Animated.Image // 可选的基本组件类型: Image, Text, View source={{uri: ‘http://i.imgur.com/XMKOH81.jpg‘}} style={{ flex: 1, transform: [ // `transform`是一个有序数组(动画按顺序执行) {scale: this.state.bounceValue}, // 将`bounceValue`赋值给 `scale` ] }} /> ); } componentDidMount() { this.state.bounceValue.setValue(1.5); // 设置一个较大的初始值 Animated.spring( // 可选的基本动画类型: spring, decay, timing this.state.bounceValue, // 将`bounceValue`值动画化 { toValue: 0.8, // 将其值以动画的形式改到一个较小值 friction: 1, // Bouncier spring } ).start(); // 开始执行动画 } }
多个动画可以通过parallel(同时执行)、sequence(顺序执行)、stagger和delay来组合使用。
Animated.sequence([ // 首先执行decay动画,结束后同时执行spring和twirl动画 Animated.decay(position, { // 滑行一段距离后停止 velocity: {x: gestureState.vx, y: gestureState.vy}, // 根据用户的手势设置速度 deceleration: 0.997, }), Animated.parallel([ // 在decay之后并行执行: Animated.spring(position, { toValue: {x: 0, y: 0} // 返回到起始点开始 }), Animated.timing(twirl, { // 同时开始旋转 toValue: 360, }), ]), ]).start();
LayoutAnimation允许在全局范围内创建和更新动画,它常用来更新flexbox布局。
var App = React.createClass({ componentWillMount() { // 创建动画 LayoutAnimation.spring(); }, getInitialState() { return { w: 100, h: 100 } }, _onPress() { // 让视图的尺寸变化以动画形式展现 LayoutAnimation.spring(); this.setState({w: this.state.w + 15, h: this.state.h + 15}) }, render: function() { return ( <View style={styles.container}> <View style={[styles.box, {width: this.state.w, height: this.state.h}]} /> <TouchableOpacity onPress={this._onPress}> <View style={styles.button}> <Text style={styles.buttonText}>Press me!</Text> </View> </TouchableOpacity> </View> ); } });
如果对性能要求比较高,setNativeProps方法可以使我们直接修改基于原生视图的组件的属性,而不需要使用setState来重新渲染整个组件树,从而可以使我们获得较好的性能。此时应该注意被render重新调用的时候覆盖掉。5.提供的调试工具开发者菜单Chrome开发者工具React开发工具插件FPS监视器6.自动化测试使用Jest进行单元测试,使用Travis作为持续集成系统。集成测试和快照测试只使用IOS。7.JS环境在IOS、Android模拟器和真机上,使用的是JavaScriptCore。在Chorme调试时,代码运行在V8引擎中。React Native从0.5.0版本开始已经内置Babel转换器,使我们可以使用最新的js语法编写代码。8.导航器官方提供提供通用跨平台的Navigator,js编写方便扩展。开源社区提供的NavigatorIOS,只能在IOS中使用,依赖Object-c,积压bug无人解决,不建议使用。9.特定平台代码将代码放在特定平台的文件夹下/common/components//android/components//ios/components/组件命名中添加平台标志BigButtonIOS.jsBigButtonAndroid.js特定平台扩展名BigButton.ios.jsBigButton.android.js在js中判断当前平台
var {Platform} = React; var styles = StyleSheet.create({ height: (Platform.OS === ‘ios‘) ? 200 : 100, });
五、已知存在的问题模块和原生视图缺失,比如Maps、Spinner等
某些属性仅仅支持单个平台 有一些已经存在的组件和API没能进行统一抽象为通用的,比如ActivityIndicatorIOS和ProgressBarAndroid overflow样式在Android中无法使用
不支持Android M(6.0)的权限
NG图片的内存问题
原文:http://www.cnblogs.com/wufengtinghai/p/5229333.html