react文字滚动插件_React-Native-Web性能优化实践

本文的项目是一个实时聊天系统。

技术栈(项目比较旧,react native、react版本没跟上):

react native 0.48.4
react native web
redux
seamless-immutable
reselect

由于是公司项目,这里就不贴源码了。

滚动长列表

优化前

287d65d850e2d6faf2d90b0d6e8a0961.png

滚动消息列表时,FlatList在每次update任务中,所有已渲染的CellRenderer都会被重新update。

这个有点不寻常,按道理已经渲染的Cell不应该update,因为消息数据并没有变化。

检查了一下代码,发现原来ListItem的props上有一个onItemLayout属性,这个属性在每次reconciler的过程中都是变化的,这就会导致PureComponent失效,每次都会进行update。

优化后

避免使用闭包,因为它每次都会生成一个新的函数,改为通过public class fields syntax来声明函数。

0b555c0b78d41f37de4884f68c254f15.png

可以看到,优化后,已渲染过的CellRenderer的颜色条变小了很多,整体的update时间从200多毫秒减少到60多毫秒!

发送消息

优化前

ac02f17e067e42361e6d9c3966a74d9c.png

发送消息时也存在同样的问题,FlatList在update时,所有已渲染的CellRenderer也被重新渲染了。

检查了一下代码,发现原来传了一个index属性,导致在发送消息时,每条消息的index都变了,所以ListItem都会被update。

由于这里的FlatList是一个reverted FlatList,所以在prepend消息时,index会整体往后移,所以导致整个列表都重绘了。

优化后

去掉index,依赖index的逻辑改为通过message id去查找计算出来。

c110f73d208f3b59a02133cb713c1fcb.png

可以看到,优化后,只有最新的一条消息会被重新update,因为它依赖了NextMessage和PrevMessage,而其他的消息就不会被update,整体update时间从200多毫秒减少到50多毫秒!

加载历史消息

优化前

e591fc527646fbf425f951bf9ddb874f.png

消息列表滚到底部后,竟然还有一个将近600毫秒的update任务。

按道理所有消息都已经加载完了,加载历史消息时,如果没有拉到新消息,应该只会更新下图所示的ListHeader:

b2fe7d16eacfd96757b25029feac391c.png

为什么会出现这么耗时的一个update任务呢?

检查了一下redux log才发现,原来是加载历史消息的逻辑有点问题。

如果本地现在已经有100条消息,当首次触发加载历史消息时,因为offset丢了,那就会一次性拉100 + 10 = 110条消息,然后query成功后,覆盖掉本地所有消息。

React收到新消息后,就会对整个消息列表进行update。

备注:因为offset没有做本地持久化,所以用户首次进入到聊天窗口,offset丢了。

优化后

这是offset算法设计上的失误,改成按最后一条消息的message id来拉取。

325ed54a93e2f2fa9ff040fc642b28b2.png

可以看到,现在确实只update了ListHeader,更新任务的时间从600毫秒减到6毫秒!

小结

以上性能问题,其实都是React常见的bad case:

  • PureComponent可能会失效,例如存在children时,每次dom diff,children都是新的element,详见 facebook/react#8669 ,常见的优化思路是把children常量化,社区也有一些专门的[babel插件](jamiebuilds/babel-react-optimize)。
  • 慎用index,特别是倒序列表,或者列表存在prepend操作等场景。
  • 慎用inline callback

最重要的还是要在实践过程中,充分利用chrome devtools等工具发现问题,优化性能问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值