React Native开发经验小结
使用shouldComponentUpdate
React提供了这个生命周期函数,来决定是否需要重新渲染该组件,为了避免无用的diff和渲染过程,需要实现这个生命周期来提升页面性能。
但也需要注意,由于会非常频繁的调用该函数,尽可能的保证其性能,以免造成反向优化的效果。
key属性
key是React中的一个特殊属性,如果我们动态创建React元素,其中包含数量不定的子元素时,我们需要添加key属性,例如:
let array = [{title: ‘a’}, {title: ‘b’}, {title: ‘c’}, {title: ‘d’}];
let views = array.map((item, index) => {
return <View key={index}/>
});
当我们改变数组数量时,React会首先比较更新前后的元素key值,如果相同则直接复用更新,而不是销毁再创建。
setNativeProps
使用该方法修改View时,不会触发组件的生命周期方法,如果需要频繁更新简单UI的组件,可以考虑使用该函数,如改变显示、隐藏回到顶部按钮,或者切换tab时,内部View的展示。
最小化DOM&组件化
React Native里虚拟Dom结构越复杂,渲染性能越低效,尽量保证层级结构少,并且将一个页面更好的划分组件粒度,保证刷新UI时少去重新做Diff运算,避免重复渲染,提高可重用性。
复杂场景避免ListView
使用FlatList/SectionList/VirtualizedList,避免使用ListView,滑动ListView内存将会显著的增加,当每条项目复杂时,如存在大量图片,考虑使用前面三种组件,避免OOM导致的应用Crash。
并且不要忘记要求服务端提供的图片在满足清晰度的情况下,尽量的小。
使用useNativeDriver
在React Native中创建动画使用Animated组件,一般使用该组件生成动画的流程如下:
1.JS端:动画驱动在每一帧上执行requestanimationframe方法,更新value,驱动不断的使用新的value计算动画视图。
2.JS端:计算差值,并且传递给绑定的view
3.JS端:使用setNativeProps来更新View
4.JS到原生桥接
5.Native端:View更新
由于大部分工作在JS端,当线程被阻塞时,动画会跳帧不流畅。RN在新版本中提供了useNativeDriver属性,在动画开始时将其序列化传递到Native端直接执行,不受JS线程阻塞影响。
动画流程变为:
1.Native端:原生动画驱动使用CADisplayLink或者android.view.Choreographer去执行每一帧,计算并更新动画视图得到的新值。
2.Native端:差值计算并被传递给绑定的原生view
3.Native端:UIView或者android.view更新
使用方法非常简单,添加useNativeDriver字段即可:
Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 500,
useNativeDriver: true, // <-- 加上这个
}).start();
iOS和Android适配问题
组件在iOS和Android上的表现不都是相同的,不要在一端上调试后就不去适配另一端,保证对双端进行必要的适配。
一些常见的需要注意的地方:
1.Text组件在Android上会存在文字的留白,导致margin距离需要单独设置
2.Image放在Text组件中时,Android上图片高度会变得和文字一样高
3.FlatList的scrollToIndex方法在iOS上存在问题
4.iOS需要注意iPhone X的适配
5.iOS上由于分辨率的问题,在Plus机型上设置View的borderWidth为0.5时,需要设置borderRadius,否则会出现边框消失的情况
6.iOS需要注意状态栏的高度,Android在设置沉浸式状态栏的时候也需要注意
7.目前Native和JS通讯在Android这里全部通过转成JSON String,iOS则是传递序列化对象
不要总是依赖React Native
React Native提供了与原生组件交互的方式,当一些场景在React Native下无法较好的表现时,不要忘记你可以使用原生组件进行开发工作,而不是全部使用JS开发,比如视频、地图组件,或者是图片、视频处理等功能。
Java、OC、Swift对于需要大量运算的工作比JS来得快的多,RN与原生的交互也比你想象的简单的多,不要在JS这棵树上吊死。