React Native 性能优化指南

2020 年谈 React Native,在日新月异的前端圈,可能算比较另类了。文章动笔之前我也犹豫过,但是想到写技术文章又不是赶时髦,啥新潮写啥,所以还是动笔写了这篇 React Native 性能优化的文章。

本文谈到的 React Native 性能优化,还没到修改 React Native 源码那种地步,所以通用性很强,对大部分 RN 开发者来说都用得着。

本文的内容,一部分是 React/RN/Android/iOS 官方推荐的优化建议,一部分是啃源码发现的优化点,还有一部分是可以解决一些性能瓶颈的优秀的开源框架。本文总结的内容你很少在网络上看到,所以看完后一定会有所收获。如果觉得写的不错,请不要吝啬你的赞,把这篇 1w 多字的文章分享出去,让更多的人看到。

看文章前要明确一点,一些优化建议并不是对所有团队都适用。有的团队把 React Native 当增强版网页使用,有的团队用 React Native 实现非核心功能,有的团队把 React Native 当核心架构,不同的定位需要不同的选型。对于这些场景,我在文中也会提一下,具体使用还需要各位开发者定夺。

目录:

一、减少 re-render

二、减轻渲染压力

三、图片优化那些事

四、对象创建调用分离

五、动画性能优化

六、长列表性能优化

七、React Native 性能优化用到的工具

一、减少 re-render

因为 React Native 也是 React 生态系统的一份子,所以很多 React 的优化技巧可以用到这里,所以文章刚开始先从大家最熟悉的地方开始。

对于 React 来说,减少 re-render 可以说是收益最高的事情了。

1️⃣ shouldComponentUpdate

文档:react.docschina.org/docs/optimi

简单式例:

class Button extends React.Component {  
    shouldComponentUpdate(nextProps, nextState) {
        if (this.props.color !== nextProps.color) {
            return true;   
        }    
        return false; 
    }  
    render() { 
        return <button color={this.props.color} />; 
    }
}

无论哪篇文章,谈到 React 性能优化,shouldComponentUpdate 一定是座上宾。

我们通过这个 API,可以拿到前后状态的 state/props,然后手动检查状态是否发生了变更,再根据变更情况来决定组件是否需要重新渲染。

官方文档对 shouldComponentUpdate 的作用原理和使用场景已经说的非常清晰了,我就没有必要搬运文章了。在实际项目中,阅文集团的 React Native 应用「元气阅读」也做了很好的示范, Twitter 的性能优化分享也做的图文并茂,可有很高的参考价值,对此感兴趣的同学可以点击跳转查看。

在此我想提醒的是,shouldComponentUpdate 是强业务逻辑相关的。 如果使用这个 API,你必须考虑和此组件相关的所有 props 和 state,如果有遗漏,就有可能出现数据和视图不统一的情况。所以使用的时候一定非常小心。

2️⃣ React.memo

文档:react.docschina.org/docs/react-

https://pos.baidu.com/s?wid=700&hei=250&di=u6883660&s1=2132101850&s2=776343018&ltu=http%3A%2F%2Fwww.kffy.cn%2Fmeiwen%2F239387.html&dc=3&ti=react%20native%20%E6%B8%85%E9%99%A4%E7%BC%93%E5%AD%98_%E6%99%B6%E7%BE%BD%E7%A7%91%E6%8A%80&ps=2788x122&drs=1&pcs=1393x835&pss=1393x6395&cfv=0&cpl=5&chi=1&cce=true&cec=UTF-8&tlm=1678931574&psr=1680x1050&par=1680x948&pis=-1x-1&ccd=30&cja=false&cmi=2&col=zh-CN&cdo=-1&tcn=1678931575&dtm=HTML_POST&tpr=1678931574892&ari=2&ant=0&exps=110281,110279,110269,110257,110009,111000,110011&prot=2&dis=0&dai=9&dri=0&ver=0308&ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3Ddk4-R7a-X0oGkfHSo9YJVfuSRH8jkDC7--WgtbeJHO19ZfKZ8ZWGMgKc7I5aV4tz%26wd%3D%26eqid%3Df320cb480008fa89000000046412762c&eqid=f320cb480008fa89000000046412762c&ecd=1&psi=57934ccf7b525eca&dft=2&ft=1

React.memo 是 React v16.6 中引入的新功能,是一个专门针对 React 函数组件的高阶组件。

默认情况下,它和 PureComponent 一样,都是进行浅比较,因为就是个高阶组件,在原有的组件上套一层就可以了:

const MemoButton = React.memo(function Button(props) { 
    return <button color={this.props.color} />;
});

如果想和 shouldComponentUpdate 一样,自定义比较过程,React.memo 还支持传入自定义比较函数:

function Button(props) {  
    return <button color={this.props.color} />;
}
function areEqual(prevProps, nextProps) { 
    if (prevProps.color !== nextProps.color) {   
        return false;   
    } 
    return true;
}
export default React.memo(MyComponent, areEqual);

值得注意的是,areEqual() 这个函数的返回值和 shouldComponentUpdate 正好相反,如果 props 相等,areEqual()返回的是 true,shouldComponentUpdate 却返回的是 false。

3️⃣ React.PureComponent

文档:react.docschina.org/docs/react-

简单式例:

class PureComponentButton extends React.PureComponent { 
    render() {    
        return <button color={this.props.color} />;  
    }
}

和 shouldComponentUpdate 相对应,React 还有一个类似的组件 React.PureComponent,在组件更新前对 props 和 state 做一次浅比较。所以涉及数据嵌套层级过多时,比如说你 props 传入了一个两层嵌套的 Object,这时候 shouldComponentUpdate 就很为难了:我到底是更新呢还是不更新呢?

考虑到上面的情况,我在项目中一般很少用 PureComponent。虽然很简单易用,但是面对复杂逻辑时,反而不如利用 shouldComponentUpdate 手动管理简单粗暴。当然这个只是个人的开发习惯,社区上也有其他的解决方案:

把组件细分为很小的子组件,然后统一用 PureComponent 进行渲染时机的管理使用 immutable 对象,再配合 PureComponent 进行数据比较( 参考链接:有赞 React 优化)......

在这个问题上仁者见仁智者见智,在不影响功能的前提下,主要是看团队选型,只要提前约定好,其实在日常开发中工作量都是差不多的(毕竟不是每个页面都有必要进行性能优化)。

二、减轻渲染压力

React Native 的布局系统底层依赖的是 Yoga 这个跨平台布局库,将虚拟 DOM 映射到原生布局节点的。在 Web 开发中,99% 的情况下都是一个 Virtual DOM 对应一个真实 DOM 的,那么在 React Native 中也是一一对应的关系吗?我们写个简单的例子来探索一下。

我们先用 JSX 写两个橙色底的卡片,除了卡片文字,第一个卡片还嵌套一个黄色 View,第二个卡片嵌套一个空 View:

// 以下示例 code 只保留了核心结构和样式,领会精神即可
render() {  
    return (  
      <View>   
          <View style={
   {backgroundColor: 'orange'}}> 
              <View style={
   {backgroundColor: 'yellow'}}>     
                  <Text>Card2</Text>     
              </View> 
          </View>   
          <View style={
   {backgroundColor: 'orange'}}> 
              <View>       
                  <Text>Card2</Text>  
              </View>    
          </View>  
      </View> 
    );
};

用 react-devtools 查看 React 嵌套层级时如下所示:

从上图中可以看出,React 组件和代码写的结构还是一一对应的。<

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值