RN性能优化总结

RN的性能优化

RN开发,遇到的问题:

  1. 打包出来的JSBundle过大;
  2. 首次进入RN页面加载缓慢;
  3. 稳定性不够,有大量因为RN导致的crash;
  4. 大数据量时候listview加载卡顿;

对于1,可以进行bundle拆包。

shouldComponentUpdate

更新阶段的生命周期

componentWillReceiveProps(object nextProps):当挂载的组件接收到新的props时被调用。此方法应该被用于比较this.props 和 nextProps以用于使用this.setState()执行状态转换。(组件内部数据有变化,使用state,但是在更新阶段又要在props改变的时候改变state,则在这个生命周期里面)

shouldComponentUpdate(object nextProps, object nextState): -boolean 当组件决定任何改变是否要更新到DOM时被调用。作为一个优化实现比较this.props 和 nextProps 、this.state 和 nextState ,如果React应该跳过更新,返回false。

componentWillUpdate(object nextProps, object nextState):在更新发生前被立即调用。你不能在此调用this.setState()。

componentDidUpdate(object prevProps, object prevState): 在更新发生后被立即调用。(可以在DOM更新完之后,做一些收尾的工作)

Tips: React的优化是基于shouldComponentUpdate的,该生命周期默认返回true,所以一旦prop或state有任何变化,都会引起重新render。

React官方的解决方案

PureRenderMixin(es5)

1
2
3
4
5
6
7
8
var PureRenderMixin = require('react-addons-pure-render-mixin');
React.createClass({
mixins: [PureRenderMixin],

render: function() {
return <div className={this.props.className}>foo</div>;
}
});

Shallow Compare (es6)

1
2
3
4
5
6
7
8
9
10
var shallowCompare = require('react-addons-shallow-compare');
export class SampleComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}

render() {
return <div className={this.props.className}>foo</div>;
}
}

es7装饰器的写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pureRender from "pure-render-decorator"
...

@pureRender
class Person extends Component {
render() {
console.log("我re-render了");
const {name,age} = this.props;

return (
<div>
<span>姓名:</span>
<span>{name}</span>
<span> age:</span>
<span>{age}</span>
</div>
)
}
}

immutable.js

Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。

【在react中使用immutable】改变shouldComponentUpdate的重新渲染规则(1)防止每次setState或传递props,即使state和props的值没有发生改变也重新渲染组件,带来无谓的性能消耗(2)防止浅比较带来的比较误差问题,以及深比较带来的性能消耗问题。

RN的列表问题FlatList

 可参看源码具体在node_modules/react-native/Libraries/Lists的目录内.

例如FlatList的源码: ../node_modules/react-native/Libraries/Lists/FlatList.js 


FlatList和SectionList通过源码可以看出,都是基于VirtualizedList的一种封装实现.
FlatList实现了单组长列表,而SectionList则实现了分组长列表.
同时也具备ScrollView的特性.

FlatList并没有采用复用机制解决内存问题,而是只渲染屏幕内的Item,超过屏幕的Item会被卸载并回收,以此来提升内存的利用率。

VirtualizedList

如果你需要更强的定制化的列表,RN的FlatList和SectionList已经不能满足你要的效果,可以在VirtualizedList上增加Wrapper来实现你的定制化。

虚拟化通过维护有限宽度的渲染窗口,并把渲染窗口之外的所有item替换为空,这样大大提高了大型列表的内存消耗和性能,滚动起来也更加的流畅。
FlatList在流畅度的提升还是很明显的,不过,在急速滚动的情况下,中间会出现白屏,这对于用户体验上来说很不友好。这里,我们可以参考VirtualizedList提供的属性来做优化。

windowSize: 限定绘制的最大数目,默认为21。

maxToRenderPerBatch:一次绘制的最大数目。

updateCellsBatchingPeriod:更新绘制的间隔时间。

initialNumToRender:首次绘制的数目。

getItemLayout:可以用来帮助我们跳过高度和位置的重新运算,当我们的每一个Item高度一致时,设置这个属性可以极大的提高渲染效率。

getItemLayout={(data, index) => (
{length: ITEM_HEIGHT, offset: (ITEM_HEIGHT+ SEPARATOR_HEIGHT) * index, index}
)}

超长列表的优化

对于列表的优化,主要集中在两个方面,一个是内存消耗,一个用户响应,用户响应又可以分为:滚动是否流畅,对点击等操作响应速度是否迅速。我们先来看看新的列表组件VirtualizedList都给我们带了哪些改进:

PureComponent: 减少不必要的渲染,如果props属性不变,它就不会重绘。 这里需要我们确保在更新props后不是===,否则UI可能无法更新更新。

限定渲染窗口: 通过维护有效项目的有限渲染窗口并把渲染窗口之外的所有元素替换为空(Blank),大大提高了大型列表的内存消耗和性能。

低优先级渲染窗口以外的区域:窗口适应滚动行为,如果项目远离可见区域,则项目将以低优先级(在任何运行的交互之后)逐渐呈现,否则为了最小化查看空格的可能性。。

异步渲染:内容将异步地渲染在屏幕外。 这意味着可能滚动会比填充率更快,看到空白的内容。 

React Native 的 ListView 性能问题已解决

文章目录
  1. 1. shouldComponentUpdate
    1. 1.1. React官方的解决方案
  2. 2. RN的列表问题FlatList
    1. 2.0.1. VirtualizedList
    2. 2.0.2. 超长列表的优化
本站总访问量 本站访客数人次 ,