微信小程序 === 长列表性能优化

news2024/11/24 12:59:49

目录

怎么做到的?

环境准备

使用开发者工具调试

开始迁移

在真机上预览效果

配置 We 分析 AB 实验

快捷切换入口

如何识别当前页面是否使用 Skyline

滚动容器及其应用场景

长列表

ScrollView 的三种模式

列表模式

自定义模式

嵌套模式

可拖拽容器


 

对于长列表出现的白屏、卡顿、界面跳动等问题,小程序提供了新 scroll-view 来解决这一系列问题。

怎么做到的?

大家肯定好奇为什么新 scroll-view 可以解决这个头疼的问题呢?

我们来对比一下新旧 scroll-view 有什么区别就可以知道答案啦~

旧 scroll-view

  • 逻辑层与渲染层的通信需要通过 JSBridge 进行转换,需要一定的时间开销
  • 渲染采用异步分块光栅化,当渲染赶不上滚动的速度,来不及渲染则会出现白屏
  • 渲染大量节点内存占用高,需要开发者自行优化只渲染在屏节点,开发成本高

新 scroll-view

  • 逻辑层与渲染层的通信无需通过 JSBridge 进行转换,减少了大量通信时间开销
  • 渲染采用同步光栅化,滚动与渲染在同一线程,不会出现白屏
  • 针对长列表进行优化,只渲染在屏节点,内存占用低,减少了一些渲染耗时,且开发接入成本低

除此之外,新 scroll-view 后续将提供 type="custom" 支持 sticky 吸顶效果、网格布局、瀑布流布局等能力便于开发者接入使用~

环境准备

Skyline 具体支持版本如下:

  • 微信安卓客户端 8.0.33 或以上版本(对应基础库为 2.30.4 或以上版本)
  • 微信 iOS 客户端 8.0.34 或以上版本(对应基础库为 2.31.1 或以上版本)
  • 开发者工具 Stable 1.06.2307260 或以上版本(建议使用 Nightly 最新版)

使用开发者工具调试

开发者工具提供了对齐移动端的 Skyline 渲染引擎,支持 WXML 调试、 WXSS 样式错误提示、新增的特性等

按以下步骤切换到 Skyline 模式:

  1. 在 app.json 或 page.json 中配上 renderer: skyline,并按下一节添加好配置项,或者按开发者工具的提示逐个加上配置项
  2. 确保右上角 > 详情 > 本地设置里的 开启 Skyline 渲染调试 选项被勾选上
  3. 使用 worklet 动画特性时,确保右上角 > 详情 > 本地设置里的 编译 worklet 代码 选项被勾选上 (代码包体积会少量增加)
  4. 调试基础库切到 3.0.0 或以上版本

开始迁移

迁移到 Skyline,无需大动干弋,我们保持了上层框架的语法、接口基本不变,只需要做局部的调整,主要是加强了 WXSS 样式、内置组件及部分特性的约束,基本流程如下:

  1. Skyline 依赖 按需注入 特性,需在 app.json 配上 "lazyCodeLoading": "requiredComponents"
  2. 在全局或页面配置中声明为 Skyline 渲染,即 app.json 或 page.json 配上 "renderer": "skyline"
  3. 在全局或页面配置中声明使用新版 glass-easel 组件框架,即 { "componentFramework": "glass-easel" }
  4. Skyline 不支持页面全局滚动,需在页面配置加上 "disableScroll": true(使之与 WebView 保持兼容),在需要滚动的区域使用 scroll-view 实现
  5. Skyline 不支持原生导航栏,需在页面配置加上 "navigationStyle": "custom"(使之与 WebView 保持兼容),并自行实现自定义导航栏
  6. 在全局配置中声明默认 block 布局,即 app.json 配上 "rendererOptions": { "skyline": { "defaultDisplayBlock": true } },详见开启默认 Block 布局
  7. 在全局配置中声明默认 content-box 布局,即 app.json 配上 "rendererOptions": { "skyline": { "defaultContentBox": true } },详见开启默认 ContentBox 盒模型
  8. 组件适配,参考 Skyline 基础组件支持与差异
  9. WXSS 适配,参考 Skyline WXSS 样式支持与差异

页面jsom

{
  "usingComponents": {
    "screenss": "../components/screenssnew/screenssnew",
    "navbar": "/components/navbar/navbar"
  },
  "renderer": "skyline",
  "componentFramework": "glass-easel",
  "disableScroll": true,
  "navigationStyle": "custom"
}

app.json

  "lazyCodeLoading": "requiredComponents",
  "rendererOptions": {
    "skyline": {
      "defaultDisplayBlock": true
    }
  }

在真机上预览效果

由于 Skyline 默认接入 We 分析的 AB 实验,未配置的情况下,页面渲染仍为 WebView 引擎,可通过以下方式正确切到 Skyline 渲染

  1. 配置 We 分析 AB 实验,加上白名单,操作步骤详见下节
  2. 关闭 We 分析 AB 实验,默认启用 Skyline 渲染,配置方式详见此处第 2 点
  3. 通过快捷切换入口,强切到 Skyline 渲染,操作步骤详见下节

配置 We 分析 AB 实验

迁移完 Skyline 之后,为了让开发者能够针对 Skyline 逐步灰度放量,并且与 WebView 对比性能表现,我们在 We 分析 提供了 AB 实验机制。

因此,需要在 We 分析 配置之后,小程序用户才可以命中 Skyline 渲染,需要注意的是,小程序开发者也会受 AB 实验影响。操作步骤如下:

首先,进入 We 分析,在 AB 实验 > 实验看板,点击“新建实验”

接着,实验类型选择 小程序基础库实验,然后按需选择实验层级并分配流量,如果是小范围调试,可分配 0% 流量,并在 Skyline 渲染 的实验分组里填上测试微信号

最后,创建实验即可生效。后续经 AB 实验验证稳定后,需在 We 分析上先关闭实验再选择 Skyline 全量

点击查看更多 We 分析 AB 实验相关内容

快捷切换入口

考虑到本地调试时,配置 AB 实验会稍微繁琐一些,并且也会需要对比 WebView 的表现,我们提供了快捷切换渲染引擎的入口。

该入口只对开发版/体验版小程序生效,入口为:小程序菜单 > 开发调试 > Switch Render,会出现三个选项,说明如下:

  • Auto :跟随 AB 实验,即对齐小程序正式用户的表现
  • WebView :强制切为 WebView 渲染。强切后,开发版、体验版、正式版均为 WebView 渲染,重启微信后恢复为 Auto
  • Skyline :若当前页面已迁移到 Skyline,则强制切为 Skyline 渲染。强切后,开发版、体验版、正式版均为 Skyline 渲染,重启微信后恢复为 Auto

如何识别当前页面是否使用 Skyline

  • 通过客户端菜单:

    打开开发版/体验版小程序,点击菜单即可查看当前页面是否使用 Skyline 渲染。 

  • 通过 vConsole 按钮的右上角的红底文案识别

  • vConsole 的路由日志

    路由日志中会包含页面路由的目标页面、路由类型和目标页面的渲染后端。

    一个可能的日志形如:On app route: pages/index/index (navigateTo), renderer: skyline,代表通过 navigateTo 跳转到了 pages/index/index,渲染后端为 skyline

  • 通过接口判断

    页面和自定义组件示例上有属性 renderer,可以用于判断当前组件的实际渲染后端,如:

    Page({
      onLoad() {
        console.log(this.renderer)
      }
    })

 

滚动容器及其应用场景

流畅的滚动对于提升用户体验至关重要。为了达到原生级别的滚动效果和降低开发成本,Skyline 扩展了旧的 ScrollView 组件,同时针对部分场景,新增了一些滚动容器。诸多的新能力有时会让开发者选择困难,下面对其典型应用场景进行介绍。

长列表

WebView 下的 ScrollView 组件,在快速滑动时容易出现白屏和渲染卡顿。对于长列表的优化,通常离不开按需渲染,即理想状态下仅渲染在屏节点,超出可视区域的节点及时进行回收。

Skyline 下内置了按需渲染的能力,但对于写法有一定要求,列表项需作为直接子节点,形如下面的结构。

<scroll-view type="list" scroll-y>
  <view> a </view>
  <view> b </view>
  <view> c </view>
</scroll-view>

视口大小

ScrollView 的视口大小 = ScrollView 的高度 + 指定的上下缓冲区 CacheExtent

指定 CacheExtent 可优化滚动体验和加载速度,但会提高内存占用且影响首屏速度,可按需启用。

节点进入视口区域时开始渲染,离开视口时回收资源。资源回收的粒度为其直接子节点。当 ScrollView 仅有单个子节点时,为保证其渲染,所有的资源都无法回收,需全量布局和绘制所有内容,性能较差,因此才需要摊平子节点。

出于业务需要 ScrollView 的内容常被封装成组件,导致无法作为直接子节点。这里有一个小技巧,可将封装的组件设为虚拟的,开启 virtualHost: true。真正渲染时,virtual-comp 节点并不存在,列表项仍是摊平的。

<scroll-view type="list" scroll-y>
  <virtual-comp>
    <view> a </view>
    <view> b </view>
    <view> c </view>
  </virtual-comp>
</scroll-view>

完全的按需渲染

小程序内的按需渲染分为两个阶段。

  1. 列表项按需创建其 DOM 节点
  2. 列表项按需绘制上屏;

ScrollView 的 list 模式实现了按需绘制,但列表项的 DOM 节点 仍是全量创建的。随着节点数增多,会带来内存压力。

为此框架提供了新的 builder 模式,可使用 list-buildergrid-builder 等组件实现 DOM 节点 的按需创建。

上图是 builder 模式在开发者工具中 wxml 的渲染结果,仅在屏列表项会被真正创建节点,离屏后列表项会被回收,滚动时始终几个子节点。

示例代码片段

在开发者工具中预览效果

ScrollView 的三种模式

ScrollView 提供了列表 list、自定义 custom 和 嵌套 nested 三种渲染模式,实际开发时如何选择呢?

列表模式

默认模式,实现了内置的按需渲染能力,但没有进行节点回收。当列表项比较简单,不会带来明显的内存压力时使用。

非长列表时,即使不摊平列表项也不会有明显性能问题,可使用单子节点写法。

<!-- 单子节点写法,全量绘制 -->
<scroll-view type="list" scroll-y>
  <view>
    <view> a </view>
    <view> b </view>
    <view> c </view>
  </view>
</scroll-view>

<!-- 列表项作为直接子节点,有按需绘制优化 -->
<scroll-view type="list" scroll-y>
  <view> a </view>
  <view> b </view>
  <view> c </view>
</scroll-view>

<!-- 列表项作为 list-view 直接子节点,有按需绘制优化,同上 -->
<scroll-view type="custom" scroll-y>
  <list-view>
    <view> a </view>
    <view> b </view>
    <view> c </view>
  </list-view>
</scroll-view>

自定义模式

列表滚动时常会和特殊布局能力结合使用,如滚动到顶部时自动吸顶 sticky 效果,或瀑布流布局。

Skyline 内置了这部分能力,可直接使用 sticky-header 和 grid-view 组件实现。

list-view 组件的效果跟列表模式是等价的,如果不需要这些特殊布局能力,可任意选择写法。

需要注意的是自定义模式下,ScrollView 直接子节点本身并没有按需绘制优化,按需绘制的能力是 list-view 组件实现的,custom 模式组合了这些能力。

<scroll-view type="custom" scroll-y>
  <sticky-section>
    <sticky-header>
      <view> h </view>
    </sticky-header>

    <!-- 非 list-view 子节点,无按需绘制优化 -->
    <view> 1</view>
    <view> 2 </view>

    <!-- 列表项作为 list-view 直接子节点,有按需绘制优化 -->
    <list-view>
      <view> a </view>
      <view> b </view>
      <view> c </view>
    </list-view>
  </sticky-section>
</scroll-view>

<scroll-view type="custom" scroll-y>
  <sticky-section>
    <sticky-header>
      <view> h </view>
    </sticky-header>

    <!-- 列表项作为 grid-view 直接子节点,有按需绘制优化 -->
    <<grid-view type="masonry">
      <view> a </view>
      <view> b </view>
      <view> c </view>
    </<grid-view>
  </sticky-section>
</scroll-view>

示例代码片段

在开发者工具中预览效果

嵌套模式

这主要是针对一类嵌套滚动场景。如下图所示,SwiperItem 内也有纵向滚动的 ScrollView 组件,当在内部 ScrollView 上滑动时,会与外层 ScrollView 产生手势冲突,导致外层的页面始终无法滚动。

  • 纵轴+横轴+纵轴的嵌套组合
  • 同一方向的滚动容器存在手势冲突
  • 可使用手势协商解决,但过程较为烦琐

为使得内外的滚动衔接更为流畅,框架新增了 <nested-scroll-header 和 nested-scroll-body 组件结合嵌套模式使用,省去了开发者解决手势的麻烦。

<scroll-view type="nested" scroll-y>
  <nested-scroll-header>
    <view></view>
  </nested-scroll-header>
  <nested-scroll-body>
    <swiper>
      <swiper-item>
        <scroll-view 
          type="list"
          associative-container="nested-scroll-view"
        >
          <view>a</view>
          <view>b</view>
        </scroll-view>
      </swiper-item>
      <swiper-item>...</swiper-item>
      <swiper-item>...</swiper-item>
    </swiper>
  </nested-scroll-body>
</scroll-view>

示例代码片段

在开发者工具中预览效果

可拖拽容器

页面内的半屏可拖拽容器是很常见的一种交互,用户可通过滚动扩大列表范围。以往开发者可通过手势协商的能力来实现,但较为繁琐。

框架提供了 draggable-sheet 组件,封装了这一能力,包括

  • 隐藏滚动条
  • 滚动回弹效果
  • 滚动到指定位置(snap 到关键点)
  • 滚动帧回调(实现滚动驱动动画)
<draggable-sheet
  class="sheet"
  initial-child-size="0.5"
  min-child-size="0.2"
  max-child-size="0.8"
  snap="{{true}}"
  snap-sizes="{{[0.4, 0.6]}}"
  worklet:onsizeupdate="onSizeUpdate"
>
  <scroll-view
    scroll-y="{{true}}"
    type="list"
    associative-container="draggable-sheet"
    bounces="{{true}}"
  />
</draggable-sheet>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2128317.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

启明云端乐鑫代理商,乐鑫ESP32无线芯片方案,物联网设备WiFi联动控制

随着智能和远程技术的飞速发展&#xff0c;物联网(IoT)逐渐出现在我们生活的每一个角落。乐鑫以其创新的无线通信技术&#xff0c;正成为智能家居、工业自动化和医疗设备等领域的推动者。 无线WiFi芯片模组不仅提供了强大的数据处理能力&#xff0c;还赋予了设备以直观的交互方…

香橙派模型转换以及部署二

由于想更新RKNN-Tookl2的版本&#xff0c;重新做一下记录。 上一篇文章安装的是RKNN-Tookl2 v1.5.2&#xff1a; 香橙派转换模型以及在开发板上部署-CSDN博客 现在记录一下RKNN-Tookl2 v2.0.0beta0版本&#xff0c;使用起来更方便&#xff0c;且可使用的功能更多一些&#x…

容联云容犀Copilot&Agent入选《中国 AI Agent 产品罗盘》

近日&#xff0c;InfoQ研究中心推出《中国AI Agent应用研究报告》&#xff0c;并在报告中对现行的中国AI Agent产品进行梳理总结&#xff0c;并形成《中国AI Agent产品罗盘》。 作为“营销服”领域垂直类Agent&#xff0c;容联云容犀Copilot&#xff06;Agent入选2024中国AI A…

天地一体化物联网:挑战与机遇

这篇论文的标题是《Space-Terrestrial Integrated Internet of Things: Challenges and Opportunities》&#xff0c;作者包括Juan A. Fraire, Oana Iova, 和 Fabrice Valois。文章发表在2022年12月的IEEE Communications Magazine上。论文主要探讨了如何将卫星通信与物联网&am…

vue3中的实例

实例类型 Vue2&#xff1a;每个Vue应用都是new Vue创建的一个新实例&#xff0c;创建的时候将data作为property添加到响应式系统中 vue3&#xff1a;createApp创建一个Application Instance、应用实例用来注册全局内容&#xff0c;大多数方法支持链式调用&#xff0c;返回实例…

C++当中的多态(二)

(三&#xff09;final和override关键字 在继承和多态当中我们还会很经常看到这两个关键字final和override。这两个关键字的作用其实很简单。 final关键字字面意思上理解就是我们这个虚函数是最后一个虚函数&#xff0c;之后不能够被重写。所以我们以后想要定义一个虚函数只能够…

word文档的读入(7)

获取了标准答案和学生答案后&#xff0c;就可以计算每位同学的填空题分数啦。我们将分数累加到studentData字典里的scoreTwo键中。需要注意的是&#xff0c;使用这个键之前&#xff0c;必须先在第一个for循环里和第二个for循环外&#xff0c;对它进行初始化赋值为0&#xff0c;…

一文搞懂线程的生命周期以及状态

一. Java 线程生命周期概述 Java 中的线程生命周期主要分为以下五个状态&#xff1a; 新建状态&#xff08;NEW&#xff09;&#xff1a;线程被创建但尚未启动。可运行状态&#xff08;RUNNABLE&#xff09;&#xff1a;线程可以被操作系统调度执行。阻塞状态&#xff08;BLO…

如何投放Spotify广告:费用与关键考量

Spotify在2008年上市时&#xff0c;市场上已经充斥着各种竞争对手的音乐服务。这款音乐流媒体应用不仅打破了预期&#xff0c;还在180个市场上吸引了超过602百万用户&#xff0c;其中包括2.36亿订阅用户。现如今&#xff0c;它是全球最受欢迎的音频流媒体订阅服务。 Spotify广…

MySQL分组查询(DQL)

先看一下我的表内容和数据&#xff0c;再做接下来的例子和讲解1.分组函数的基本用法 select 字段列表 from 表名 [WHERE 条件] group by 分组字段名 [HAVING 分组后的过滤条件] 2.先声明where和having的区别 1.执行时机不同&#xff1a;where是分组之前进行过滤&#xff0c;…

❤Node08-Express-jwt身份认证

❤Node08-Express-jwt身份认证 1、token基本概念​ Session认证的局限性​ Session 认证机制需要配合Cookie才能实现。由于 Cookie 默认不支持跨域访问&#xff0c;所以&#xff0c;当涉及到前端跨域请求后端接口的时候&#xff0c;需要做很多额外的配置&#xff0c;才能实现…

特征值特征向量

正交矩阵 施密特正交化,本质上是正交​编辑投影定理的应用

再次进阶 舞台王者 第八季完美童模全球赛荣耀大使【李暖希】赛场秀场超燃合集!

7月20-23日&#xff0c;2024第八季完美童模全球总决赛在青岛圆满落幕。在盛大的颁奖典礼上&#xff0c;一位才能出众的少女——李暖希&#xff0c;迎来了她舞台生涯的璀璨时刻。 荣耀大使——李暖希&#xff0c;以璀璨童星之姿&#xff0c;优雅地踏上完美童模盛宴的绚丽舞台&am…

Python爱心射线(完整代码)

目录 系列目录 写在前面​ 完整代码 下载代码 代码分析 写在后面 系列目录 序号直达链接表白系列1Python制作一个无法拒绝的表白界面2Python满屏飘字表白代码3

【工资计算 / 2】

题目 枚举 #include <bits/stdc.h> using namespace std; int T; int a[] {0,1500,4500,9000,35000,55000,80000,1000000}; int b[] {0,3,10,20,25,30,35,45}; int check(int x) {if(x < 3500) return x;x - 3500;int tax 0;for(int i 1; i < 8; i){if(x >…

【Spring Boot 整合 MyBatis 详细教程】

文章目录 Spring Boot 整合 MyBatis 详细教程简介环境准备项目搭建项目结构配置项目1. pom.xml 配置2. 数据源和 MyBatis 配置3. 启动类配置4. Mapper 接口和 XML 映射文件 测试总结 Spring Boot 整合 MyBatis 详细教程 简介 Spring Boot 与 MyBatis 的整合可以让你轻松地构建…

Unity射击游戏开发教程:(35)轰炸敌人

现在敌人和飞机已经慢慢地越来越有各自地地行为了,在本文中,我们将介绍如何创建一个具有以下行为的敌人: 飞机会来回弹跳。飞机将有 4 架无人机轰炸机围绕飞机旋转。无人机轰炸机会偶尔投下沿着屏幕传播的炸弹。如果炸弹击中玩家或在随机时间后就会爆炸。如果炸弹没有击中玩…

机器学习--逻辑回归

逻辑回归 前情提要&#xff1a;线性回归 关于分类 C l a s s i f i c a t i o n Classification Classification 在逻辑回归中&#xff0c;我们只讨论 y ∈ { 0 , 1 } y\in\{0, 1\} y∈{0,1} 的情况。其中 1 1 1 表示 p o s i t i v e c l a s s positive \; class posit…

无人机培训机构组装调试技术详解

一、基础知识学习 在进入无人机组装调试领域之前&#xff0c;扎实的基础知识是不可或缺的。学员需掌握以下内容&#xff1a; 1. 无人机基本原理&#xff1a;了解无人机的飞行原理&#xff0c;包括升力、推力、重力和阻力等基本物理概念&#xff0c;以及无人机的飞行控制系统&…

CSP-J 初中的数学知识要学完, CSP-S 肯定是要需高中的知识

学信奥赛好处很多&#xff0c;进则科技特长&#xff0c;退则数理化强。