如何合理使用动效来获得更好的性能
组件转场动画使用 transition:
推荐使用转场动画(transition)而不是组件动画(animateTo),因为 transition 只需要在条件改变时更新一次,而 animateTo 需要在动画前后做两次属性更新,导致性能开销更大。
反例:通过改变透明度属性并使用 animateTo 来隐藏和显示组件。
正例:直接使用 transition 动画,通过改变透明度实现组件的出现与消失。
组件布局改动时使用图形变换属性动画:
当需要改动组件的布局显示时,推荐使用图形变换属性(如平移、旋转、缩放)而不是改动布局属性(如 width、height、layoutWeight),因为图形变换不会重新触发布局,从而减少性能开销。
反例:通过设置布局属性 width 和 height 来改变组件大小。
正例:通过设置图形变换属性 scale 来改变组件大小。
动画参数相同时使用同一个 animateTo:
如果多个属性需要使用相同的动画参数进行动画处理,应该将它们合并到一个 animateTo 闭包中,以减少组件更新的次数。
反例:将相同动画参数的状态变量更新放在不同的动画闭包中。
正例:将相同动画参数的动画合并在一个动画闭包中。
多次 animateTo 时统一更新状态变量:
在执行多个 animateTo 之前,应该统一更新状态变量,避免在执行动画之间产生冗余的状态更新。
反例:在两个 animateTo 之间更新状态变量。
正例 1:在 animateTo 之前使用原始状态,让动画从原始状态过渡到指定状态。
正例 2:在 animateTo 之前显式指定所有需要动画的属性初值,统一更新到节点中,然后再执行动画。
应用性能提升
1. 使用数据懒加载
在处理长列表数据时,传统的循环渲染方式会一次性加载所有列表元素,这会导致页面启动时间过长,影响用户体验,并增加服务器压力。为了解决这个问题,推荐使用 DataSource 来实现数据懒加载技术。通过懒加载,只有当数据进入可视区域时才加载和渲染,这样可以显著提高页面的响应速度和性能。
2. 设置 List 组件的宽高
在使用 Scroll 容器组件嵌套 List 组件加载长列表时,如果没有指定 List 的宽高尺寸,List 将会布局其所有子组件,这会导致性能问题。通过设置 List 的宽高,可以确保只布局 List 显示区域内的子组件,从而提高性能。
Scroll 嵌套 List 时:
List 没有设置宽高,会布局 List 的所有子组件。
List 设置宽高,会布局 List 显示区域内的子组件。
List 使用 ForEach 加载子组件时,无论是否设置 List 的宽高,都会加载所有子组件。
List 使用 LazyForEach 加载子组件时,没有设置 List 的宽高,会加载所有子组件,设置了 List 的宽高,会加载 List 显示区域内的子组件。
3. 使用条件渲染替代显隐控制
使用 visibility 属性控制组件的显隐状态时,即使组件不可见,它仍然会被重新创建,这会造成性能损耗。通过使用 if 条件渲染,可以避免组件的重新创建过程,从而提升性能。
4. 使用 Column/Row 替代 Flex
Flex 容器组件在默认情况下存在 shrink 属性,这可能导致二次布局,影响页面渲染性能。通过使用 Column 和 Row 组件替代 Flex,可以避免二次布局带来的性能问题。
5. 减少应用滑动白块
在应用中,滑动白块是一个常见的性能问题。通过增大 List/Grid 控件的 cachedCount 参数,可以预加载更多的 item,减少白块的出现。同时,如果需要请求网络图片,可以提前下载内容,以减少滑动时的白块现象。
状态管理优化
以下是文档中提到的一些关键点:
使用@ObjectLink 代替@Prop 减少不必要的深拷贝:
在父子组件间传递数值时,如果子组件不需要改变状态变量的值,使用@ObjectLink 比@Prop 更优,因为@Prop 会导致深拷贝,增加性能开销。
不使用状态变量强行更新非状态变量关联组件:开发者应避免通过改变自定义的 UI 状态变量来带动常规变量的更新,而应将相关成员变量用@State 装饰,以便框架能够检测状态变化并触发 UI 更新。
精准控制状态变量关联的组件数:建议每个状态变量关联的组件数少于 20 个,以减少不必要的组件刷新,提高效率。
合理控制对象类型状态变量关联的组件数量:如果一个复杂对象被定义为状态变量,需要合理控制其关联的组件数,避免“冗余刷新”。
查询状态变量关联的组件数:可以使用 HiDumper 工具查看状态变量关联的组件数,进行性能优化。
避免在 for、while 等循环逻辑中频繁读取状态变量:应该在循环外面读取状态变量,避免在循环逻辑中频繁读取,以提高性能。