• 【网上摘录】React Native APP性能优化


      1、JS的单线程

      所有的事件处理,API请求,等操作都在这个线程上,在this.setState大量数据时,状态的变动会导致re-render,这期间所有由JavaScript 控制的动画都会出现卡顿掉帧。

      比如在切换路由时,帧数会有明显抖动。此时如果有一些在componentDidMount 执行的操作就会使得路由过渡动画非常卡顿。

      2、开发环境性能比生产环境差

      开发环境下框架会有很多别的操作比如warning error 的输出,类型检测等等。

      如果要测试性能,最好在release 包测试。这样更加精准。

      3、生产环境移除console.*

      开发时,会有很多console.* 指令来帮助调试。并且一些依赖库也会有console.* 这些语句对JavaScript 线程来说是一个极大的消耗。可以通过Babel 在生产环境中移除掉console.*

    • 安装插件

      npm i babel-plugin-transform-remove-console --save-dev

    • 配置.babelrc 文件

      {
        "env": {
          "production": {
            "plugins": ["transform-remove-console"]
          }
        }
      }

      4、处理大量数据列表式使用<FlatList/>

      FlatList 组件更加适合来展示长列表,并且指定合适的 getItemLayout 方法, getItemLayout 会跳过渲染Item 时的布局计算,直接使用给定的配置(详情查看链接☝️)

      5、依赖懒加载

      在框架执行编写好的业务代码前,需要把在内存中加载并解析代码,代码量越大这个过程就更耗时,导致首屏渲染速度过慢。而且往往会出现一些页面或者组件根本不会被用户访问到。这时可以通过懒加载来优化。

    import xxx from './xxxx'
    
    let test2;
    
    export default class Test extent Componnet {
    
        getTest2 = ()=>{
            // 对test2模块进行懒加载(延迟加载),以提高性能
            if(test2 === undefined) {
                test2 = require('./xxxx/test2');
            }
        }
    }

      6、优化组件渲染次数

      React 在内部state 或者外部传入的props 发生改变时,会重新渲染组件。如果在短时间内有大量的组件要重新渲染就会造成严重的性能问题。这里有一个可以优化的点。

    • 使用PureComponent 让组件自己比较props 的变化来控制渲染次数,实践下来这种可控的方式比纯函数组件要靠谱。或者在Component  中使用 shouldComponentUpdate 方法,通过条件判断来控制组件的更新/重新渲染。
    • 使用PureComponent 时要注意这个组件内部是浅比较状态,如果props 的有大量引用类型对象,则这些对象的内部变化不会被比较出来。所以在编写代码时尽量避免复杂的数据结构
    • 细粒度组件,拆分动态/静态组件。需要在项目稳定并有一定规模后来统一规划。
    • 学习 immutable-js

      7、异步,回调

      JavaScript 单线程,要利用好它的异步特性,和一些钩子回调。

      比如上面提到路由切换时componentDidMount 中的操作会导致卡顿,这里可以使用 InteractionManager.runAfterInteractions() 将需要执行的操作放到runAfterInteractions 的回调中执行。

    componentDidMount() {
        InteractionManager.runAfterInteractions(() => {
            // your actions
        })
    }

      需要注意的是 InteractionManager 是监听所有的动画/交互 完成之后才会触发 runAfterInteractions 中的回调,如果项目中有一些长时间动画或者交互,可能会出现长时间等待。所以 由于 InteractionManager 的不可控性,使用的时候要根据实际情况调整。

      在react-native 中的一些动画反馈,比如TouchableOpacity 在触摸时会响应 onPress 并且 自身的透明度会发生变化,这个过程中如果 onPress 中有复杂的操作,很可能会导致组件的透明反馈卡顿,这时可以将onPress 中的操作包裹在 requestAnimationFrame 中。这里给出一个我的实践(利用styled-component)

    import styled from 'styled-components'
    
    export const TouchableOpacity = styled.TouchableOpacity.attrs({
      onPress: props => () => {
        requestAnimationFrame(() => {
          props.onPressAsync && props.onPressAsync()
        }, 0)
      }
    })``

      这里把onPress 改成在 requestAnimationFrame 的回调中执行onPressAsync 传入的操作。

      同理,还在FlatList 的onReachEnd实践了这个操作,来避免iOS 中滚动回弹时执行操作的卡顿。

      8、为同层级的相同类型的组件设置key值

      对于同层级的相同类型的组件,要给每个组件指定唯一的key值。例如通常我们在一个容器组件中创建多个子组件的时候,我们会把这些子组件放在一个数组里,然后把数组直接放到容器页面中,形如下面的伪代码:

    banner = ()=>{
        let childArr = [];
        while(let i < 10) {
            childArr.push(<Child key={XXXXXX}></Child>)
        }
        return <View> {childArr} </View>
    }
      Child组件的key一定要有,这涉及到diff算法的原理,diff算法是按层级进行比较的,当前的virtual DOM 和之前的virtual DOM进行同层级比较的时候,对于属于同一个父组件的同一层级的子组件,如果没有key值的话,RN需要遍历该父组件的所有子组件来行进对比,才能知道哪一个子组件发生了改变,这样如果子组件的数量很大的时候会很耗性能,RN有可能会因为遍历的耗时而选择放弃对比来重新渲染所有的子组件,但是如果有key值的话可以利用key直接进行两两比较,效率就高出很多。
      感谢各位网友的无私分享。
  • 相关阅读:
    蓝鸥0c考试 绝密
    省市县用对象实现
    省市区用字典实现
    3道比较有用的oc练习题
    ios 开发 OC编程 类的扩展 协议 延展和 类目
    ios 开发 OC编程 内存管理
    ios 开发 OC编程 块语法bolck的一些应用
    ios 开发 OC编程 块语法bolck
    中等难度的通讯录.字典 动态分组法
    TestFlight
  • 原文地址:https://www.cnblogs.com/xjf125/p/12388432.html
Copyright © 2020-2023  润新知