---
title: 渲染性能优化
summary: "介绍渲染性能优化方法，包括减少节点数、选择高性能动画方案和组件化拆分。"
docType: default
tags: [渲染性能优化, 自定义组件粒度优化, CSS动画替代JS动画, WXML节点精简]
questions:
  - 页面节点数过多会带来什么性能问题？
  - 如何减少页面的节点数量？
  - 条件渲染和 display:none 在性能上有什么区别？
  - 如何合理监听滚动事件以避免性能问题？
  - 小程序中有哪些动画实现方式，各自性能如何？
  - 为什么推荐使用 transform 和 opacity 做动画？
  - 组件化拆分如何提升渲染性能？
---

# 渲染性能优化

渲染性能影响页面的流畅度和响应速度。页面结构越复杂、更新越频繁，渲染压力越大。

## 减少页面节点数

页面中节点数过多会增加内存占用和布局计算耗时。建议一个页面节点数少于 1000 个，节点树深度少于 30 层。

常用手段：

- **移除冗余嵌套**：减少不必要的 `View` 包裹层，保持结构扁平
- **条件渲染**：暂时不需要展示的内容用 `{condition && ...}` 而不是 `display: none`；如果元素需要频繁切换，改用 `hidden` 属性避免反复创建销毁节点

```tsx
import { View } from '@ray-js/ray';

{/* ✅ 用条件渲染移除不需要的节点 */}
{showDetail && (
  <View className="detail-content">...</View>
)}
```

## 合理监听滚动事件

`onPageScroll` 和 `ScrollView` 的 `onScroll` 事件触发频率很高，每次触发都会有跨线程通信开销。

注意事项：

- 非必要不监听 scroll 事件
- 不需要时不要传入空的 `onPageScroll` 函数
- 避免在 scroll 回调中频繁调用 `setState` 或同步 API

## 选择高性能的动画实现方式
动画是提升小程序交互体验的重要手段。选择合适的动画实现方式可以在保证视觉效果的同时避免性能问题。

| 方案 | 适用场景 | 性能 | 复杂度 |
| ---- | -------- | ---- | ------ |
| CSS 动画 / Transition | 简单过渡效果（显隐、位移、缩放） | 高 | 低 |
| GIF / Lottie | 装饰性动画（加载动画、图标动效） | 高 | 低 |
| [RJS](/cn/miniapp/develop/ray/framework/render) | 高频交互动画（跟手拖拽、手势联动） | 高 | 高 |
| setData 驱动 | - | 低 | 低 |

- 优先使用 `transform` 和 `opacity` 属性做动画，它们可以使用 GPU 加速
- 避免对 `width`、`height`、`margin`、`padding` 等属性做动画，它们会触发布局重排

```css
/* ✅ 推荐：使用 transform */
.slide-in {
  transform: translateX(-100%);
  transition: transform 0.3s ease;
}
.slide-in.active {
  transform: translateX(0);
}

/* ❌ 避免：使用 left/right */
.slide-in {
  left: -100%;
  transition: left 0.3s ease;
}
```

避免用 `setState` 每帧更新状态来驱动动画。在 60fps 的要求下每帧只有约 16ms，跨线程通信耗时会导致严重掉帧。高频交互动画（如拖拽跟手）使用 RJS 在视图层直接响应事件和修改样式。

## 组件化拆分

将页面拆分为独立的子组件，组件内的状态更新只会触发组件自身重新渲染，不会影响整个页面：

```
页面
├── Header 组件（独立更新）
├── ListItem 组件 × N（各自独立更新）
└── Footer 组件（独立更新）
```

## 检查清单

| 检查项 | 优化方法 |
| ------ | -------- |
| 页面节点数是否过多 | 移除冗余嵌套，简化结构 |
| 是否用 `display:none` 隐藏大量节点 | 改用条件渲染 |
| 是否监听了不必要的滚动事件 | 移除空回调 |
| 动画是否卡顿 | 改用 CSS 动画或 RJS |
| 页面是否进行了组件化拆分 | 将独立模块提取为子组件 |
