React Native 的性能应该一直是大家关心的重点,我们也会经常说到 React Native 应用的主要优势在于性能比较好,但其背后的主要原因之一得归功于其高效的渲染能力。
除了上一篇文章:juejin.cn/post/729565... 分析到的我们可以在应用打开阶段通过 JavaScript Engine 的方式优化应用页面打开阶段遇到的白屏和加载时间过长的问题,我们也可以在 React Native 应用运行过程中进行优化。
而在应用运行过程中渲染是非常重要的一部分,运行时会分别创建三个线程:JS Thread、Shadow Thread、Main Thread,在这三个线程中分别会创建三棵树,JS线程中会创建 Fiber Tree,在Shadow 线程中会创建 Shadow Tree,在UI线程中会创建 View Tree。
首先在 React Native 应用中需要在构建 fiber 对象,其次通过桥的方式通知 UI Manage 构建一颗 Shadow Tree,最后 Native 根据 Shadow Tree 映射成 Native 元素并渲染。
所以至少从流程上面来看,整个渲染是相对复杂和繁琐的,那应该如何去做好渲染缓解的优化工作呢?
渲染优化的办法
更多时候在渲染上的优化都是在 React render 阶段进行,其中可以实施的方法有好几种,这里主要介绍4种我个人认为比较常用到的方式:
1、使用 PureComponent
首先需要说明下,PureComponent 是一种特殊的组件,它会在其 props 或 state 发生变化时进行浅比较。如果 props 或 state 没有发生变化,则 PureComponent 不会重新渲染。这可以大大提高渲染性能,尤其是当组件的 props 或 state 经常发生变化时。
scala
import React from "react"
import { View, TouchableOpacity, Text } from "react-native"
class Children extends React.PureComponent{
//...
}
2、使用 shouldComponentUpdate
在有的时候,我们单纯把控制渲染性能调优交给 React 组件本身处理显然是靠不住的,React 需要提供给使用者一种更灵活配置的自定义渲染方案,使用者可以自己决定是否更新当前组件,shouldComponentUpdate 就能达到这种效果。
shouldComponentUpdate 是一种生命周期方法,它会在组件的 props 或 state 发生变化时被调用。如果 shouldComponentUpdate 返回 false,则组件不会重新渲染。这可以大大提高渲染性能,尤其是当组件的 props 或 state 经常发生变化时。
要使用 shouldComponentUpdate,只需在组件中定义该方法即可。这里举一个例子:
scala
class MyComponent extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
// ...
return true;
}
// ...
}
3、使用 React.memo
React.memo 是一种函数,可作为一种容器化的控制渲染方案,它可以将一个组件包装成一个新的组件,该组件会在其 props 或 state 发生变化时进行浅比较。如果 props 或 state 没有发生变化,则新组件不会重新渲染。这可以大大提高渲染性能,尤其是当组件的 props 或 state 经常发生变化时。
要使用 memo,只需将其作为组件的包装函数即可。例如:
javascript
const MyComponent = memo(function MyComponent(props) {
// ...
});
4、缓存React.element对象
React.element 是一种父对子的渲染控制方案,缓存了 element 对象。这里我们可以先看看这里一个示例:
javascript
import React from "react"
import { View, TouchableOpacity, Text } from "react-native"
function Children () {
return <View>子组件</View>
}
function App(){
const [ number, setNumber ] = React.useState(0)
/* 这里把 Children 组件对应的 element 元素缓存起来了 */
const children = React.useMemo(()=><Children />,[])
const onPress = () => setNumber(number => number + 1);
return <View >
父组件
<TouchableOpacity onPress={onPress} >
<View>
<Text>add</Text>
</View>
</TouchableOpacity>
</View>
}
当然在渲染环节还有其他的方法,例如 StyleSheet 、useCallback、Animated 库等,都能在一定程度上提高应用的性能,并使其更流畅。