• 开发教程与代码示例
  • 入门
  • 小程序框架
  • 小程序运行时
  • 自定义组件
  • 基础教程
  • 能力教程
  • 性能优化
  • 概述
  • 性能优化辅助平台/工具
  • 性能优化方法
  • 启动性能
  • 运行时性能
  • 概述
  • 小程序运行时性能优化
  • 小程序白屏&渲染异常问题优化
  • 安全
  • 小程序运行时性能优化
    收藏
    我的收藏

    小程序的运行时性能直接决定了用户在使用小程序功能时的体验。如果运行时性能出现问题,很容易出现页面滚动卡顿、响应延迟等问题,影响用户的使用。如果内存占用过高,还会出现黑屏、闪退等问题。
    结合小程序的运行原理,我们可以考虑从以下几个方面进行优化。

    合理使用 setData

    setData 的过程,大致可以分成几个阶段:
      1.逻辑层虚拟 DOM 树的遍历和更新,触发组件生命周期和 observer 等
      2.将 data 从逻辑层发送到视图层
      3.更新视图层虚拟 DOM 树、真实 DOM 元素并触发页面渲染
    由于小程序的逻辑层和视图层是两个独立的运行环境,不能直接进行数据共享,需要进行数据的序列化、跨线程/进程的数据传输、数据的反序列化,因此数据传输过程是异步的、非实时的。数据传输的耗时与数据量的大小正相关,如果对线程处于繁忙状态,数据会在消息队列中等待,导致处理队列阻塞,界面渲染不及时而导致卡顿,应避免无用的频繁调用。具体优化手段有:
      合并发送数据。频繁的数据更新会导致页面不断重新渲染,导致渲染线程繁忙,进而阻塞交互事件的响应
      不发送与页面渲染无关的数据。setData 是作为页面渲染数据更新的来源,与页面渲染无关的数据可以存储到本地或挂载到页面或全局对象
      处于后台不调用。后台态页面的渲染用户是无法感受的,另外后台态页面去 setData 也会抢占前台页面的执行,造成不必要的性能开销
      不在高频事件中调用。如 scroll 事件中
      动画减少使用 setData。优先使用 CSS 渐变、CSS 动画

    控制 TTML 节点数量和层级

    节点树太大会增加内存的使用,样式重排时间也会更长,影响体验。建议一个页面 TTML 节点数量应少于 1000 个,节点树深度少于 30 层,子节点数不大于 60 个。

    合理使用自定义组件

      合理拆分自定义组件。Page 中的 setData 会触发渲染层以页面级别进行 diff 操作,如果页面比较复杂且没有使用自定义组件,那么 diff 的成本会很高,导致体验比较差(更新卡顿、不粘手等感受)。如果页面转换为若干个组件,组件中 setData, 只会触发渲染层对应组件的 diff 操作,diff 成本会降低很多,使用体验也会更优。但自定义组件的使用会引入前置的注册和自定义组件生命周期执行逻辑,因此建议将业务逻辑比较独立或变更频率较大的部分进行拆分,避免盲目拆分
      只注册当前使用的组件。为了保证自定义数据在不同的页面实例中也是不同的实例,小程序框架会在页面创建时对这部分数据(函数类型字段除外)做一次深拷贝,如果自定义数据过多或过于复杂,可能带来很大的开销。因此建议在usingComponents中应只注册当前页面有使用到的自定义组件
      按需使用同步修改 data 的能力。在app.json 中增加配置component2: true 后,支持在 created 生命周期中修改自定义组件初始数据,自定义组件将在created 生命周期执行完成后开始渲染。
      开启后有以下优化点:避免由于 data 变化导致页面渲染内容闪动或频繁变动问题
      开启后的限制:避免在 created 中如果有较多同步逻辑,同步过多会影响小程序性能

    合理监听事件

      合理监听和处理 scroll 事件。scroll 事件中高频执行耗时操作,会明显降低 FPS
      去掉不必要的事件绑定。过多的事件绑定(ttml 中的 bind 和 catch),也会增大通信的数据量和次数。渲染层会接受用户事件,如点击事件、触摸事件等。用户事件的通信过程:当一个用户事件被触发且有相关的事件监听器需要被触发时,渲染层会将信息反馈给逻辑层。如果一个事件没有绑定事件回调函数,则这个事件不会被反馈给逻辑层

    内存优化

      及时解绑事件监听。事件监听结束后,应及时解绑监听器
      及时清理定时器。开发者在开发如「秒杀倒计时」等功能时,可能会使用 setInterval设置定时器,页面或组件销毁前,需要调用clearInterval 方法取消定时器

    导航栏适配

    清晰的导航能告诉用户当前在哪里、能到哪里去、并能原路返回。除了默认的导航栏外,开发者也可以根据需求申请权限,设计自定义导航栏适配小程序风格。
      适当开启自定义导航栏。避免在app.json中全局开启动态导航栏,仅在需要的页面中配置,降低适配成本
      关键信息避开状态栏和胶囊按钮。如果开启自定义导航栏,需要通过 tt.getCustomButtonBoundingClientRect 获取自定义导航栏下不可改变的元素位置信息以适配导航栏

    适配分屏

    正常情况下页面默认是撑满整个视口的,但在直播小程序卡片、POI 详情页商品入口会出现七分屏场景。
      通过 onResize 监听显示区域变化。小程序支持组件和页面的生命周期函数 onResize 用于在显示区域的尺寸发生变化的时候返回当前页面的信息。其中组件需要作为页面配置到app.json 中触发事件
      不使用 JS 设置 ScrollView 高度。scroll-view 中分屏变为全屏时需要重新设置 scroll-view 高度,可能会出现空白区域问题,建议使用 CSS(vh)完成自适应布局
    通过以上几个方面的优化方向,我们可以在一定程度上提升小程序运行时的使用体验,启动阶段的优化可以移步小程序启动性能优化。开发过程中也可以使用体验评分工具来检测更多的小程序性能问题。