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

server/2024/9/18 23:15:31/ 标签: 微信小程序, 小程序

目录

怎么做到的?

环境准备

使用开发者工具调试

开始迁移

在真机上预览效果

配置 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-sheetclass="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-viewscroll-y="{{true}}"type="list"associative-container="draggable-sheet"bounces="{{true}}"/>
</draggable-sheet>


http://www.ppmy.cn/server/115638.html

相关文章

Python数据分析及可视化教程--商城订单为例-适用电商相关进行数据分析---亲测可用!!!!

前言:Python 是进行数据分析和可视化的强大工具,常用的库包括 Pandas、NumPy、Matplotlib 和 Seaborn。以下是一个基本的教程概述,介绍了如何使用这些库来进行数据分析和可视化: Python数据分析及可视化教程 1、 环境准备2、数据准备3、开始数据分析3.1、导入库3.2、加载数…

关于java学习基础路线的分享【javaSE】

成长路上不孤单&#x1f60a;【14后&#xff0c;C爱好者&#xff0c;持续分享所学&#xff0c;如有需要欢迎收藏转发&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#xff01;&#xff01;&#xff01;&#xff01;&#xff…

优化你的MySQL查询:12个必备的SQL书写习惯!

良好的书写SQL习惯 非常重要&#xff0c;原因如下&#xff1a; 结构良好的 SQL 语句提高了可读性&#xff0c;更容易理解、维护和调试。优化后的SQL查询可以更快地执行&#xff0c;减少服务器的工作负担&#xff0c;从而提高数据库性能。遵循最佳实践可以避免SQL注入等安全问题…

使用PHP和MQTT构建高效的物联网数据转发服务器流程

一、项目概述 项目目标和用途 本项目旨在搭建一个基于PHP的物联网服务器&#xff0c;能够接收来自各种传感器的数据&#xff0c;并通过MQTT协议将数据转发到其他设备或服务。该系统适用于智能家居、环境监测等场景&#xff0c;能够实现实时数据监控和远程控制。 技术栈关键词…

我是Redis,请看我和mysql是如何交互的吧~

1. 数据查询&#xff1a;先找我 Redis 过程描述&#xff1a;当有数据请求时&#xff0c;程序首先会找我&#xff08;Redis&#xff09;查询。因为我是在内存中工作的&#xff0c;查询速度非常快。如果我有数据&#xff0c;就直接返回&#xff0c;避免查询 MySQL。如果我没有缓…

JavaScript 生成随机数、随机颜色、随机字符串等的几种方式

在 JavaScript 中&#xff0c;生成随机数是一个常见的需求&#xff0c;尤其是在游戏开发、数据分析和测试等领域。以下是几种在 JavaScript 中生成随机数的方法&#xff1a; 1. 使用 Math.random() Math.random() 函数返回一个浮点数&#xff0c;范围从 0&#xff08;包含&am…

【自学笔记】支持向量机(1)

一些概念 支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;是一种广受欢迎的监督学习算法&#xff0c;主要用于分类和回归分析。在分类问题中&#xff0c;SVM的主要目标是在训练数据中找到一个超平面。这个超平面不仅能够准确地区分不同类别的样本…

MFC生成dll的区别

主要分三种&#xff1a; A. 动态链接库(dll) B.具有导出项的(dll)动态链接库 C.MFC动态链接库 对比项目&#xff1a;可以根据需要选择哪种dll方便 添加自定义导出功能Demo 1. 添加导出实现接口&#xff1a; A. 导出需要具有&#xff1a;__declspec(dllexport) B. 按照C语言…

【笔记】408刷题笔记

文章目录 三对角三叉树求最小带权路径UDP报文首部和TCP报文首部IP报文首部TCP报文首部UDP报文首部 刷新和再生的区别地址译码 为了区分队空队满&#xff0c;可以使用三种处理方式 1&#xff09;牺牲一个单元 队头指针在队尾指针的下一位置作为队满的标志 队满条件&#xff1a;(…

终端显示字体背景和字体颜色

【终端显示字体背景和字体颜色等使用用法】 在命令行下想要产生五颜六色的字体和背景&#xff0c;只需要加上一些颜色代码即可。 ANSI 标准规定了一种所有终端共享的指令集&#xff0c;并要求用 ASCII 的数字字符传递所有数值信息&#xff0c;用于控制 Linux 终端上的光标位置…

使用C++实现一个支持基本消息传递的TCP客户端和服务器

使用C实现一个支持基本消息传递的TCP客户端和服务器 在网络编程中&#xff0c;TCP&#xff08;Transmission Control Protocol&#xff09;是一种常用的协议&#xff0c;用于在计算机之间建立可靠的连接。通过实现一个TCP客户端和服务器&#xff0c;可以深入理解TCP协议的工作…

绩效考核自动化:SpringBoot月度管理

第2章 系统需求分析与系统开发分析 2.1系统的需求分析 古往今来&#xff0c;对于企业员工绩效考核的管理一直存在&#xff0c;主要的管理方式就是人工加计算机结合进行管理。在签到中采用签到机进行&#xff0c;在数据统计中采用人工进行。这种方式的缺点就是不能用于中大型规模…

Python(PyTorch)和MATLAB及Rust和C++结构相似度指数测量导图

&#x1f3af;要点 量化检查图像压缩质量低分辨率多光谱和高分辨率图像实现超分辨率分析图像质量图像索引/多尺度结构相似度指数和光谱角映射器及视觉信息保真度多种指标峰值信噪比和结构相似度指数测量结构相似性图像分类PNG和JPEG图像相似性近似算法图像压缩&#xff0c;视频…

3GPP How to manage a project?

有人问:"3GPP 每个release都做了哪些方面的增强&#xff1f;应该有专门的文档介绍吧?"那肯定是有的&#xff0c;其实按照 https://t.zsxq.com/zbSox 中的方法就能找到那个文档。这篇我们整体浏览看下3GPP是如何handle project&#xff0c;这其中就会具体涉及哪些内…

pytorch 报错 the graph are freed when you call .backward() or autograd.grad()

原来 的环境 是 python 3.7 torch1.13.1 环境 下面跑通的代码 到 python 3.10 和torch 2.3.1报错 File "/mnt/workspace/t.py", line 200, in train d_loss.backward() File "/usr/local/lib/python3.10/site-packages/torch/_tensor.py", line 5…

SQL COUNT() 函数深入解析

SQL COUNT() 函数深入解析 SQL&#xff08;Structured Query Language&#xff09;是一种用于管理关系数据库管理系统&#xff08;RDBMS&#xff09;的标准编程语言。在SQL中&#xff0c;COUNT() 函数是一个常用的聚合函数&#xff0c;用于计算数据表中的行数或特定列的值数量…

如何设计实现完成一个FPGA项目

设计并完成一个FPGA项目是一个复杂但非常有价值的工程任务。以下是一个详细的步骤指南,帮助你从零开始完成一个FPGA项目。 1. 项目定义与需求分析 确定项目目标:明确项目要实现的功能和性能指标。需求分析:列出所有功能需求、性能需求、接口需求等。可行性分析:评估技术可…

让孤独症儿童学校生活充满乐趣与成长

在探索自闭症儿童成长的广阔天地中&#xff0c;每一份细心与创意都是点亮他们心灵之光的宝贵火种。星贝育园&#xff0c;这所专为自闭症儿童设计的寄宿制学校&#xff0c;便是一个将爱与智慧巧妙融合&#xff0c;让孤独症孩子们的校园生活不仅充满乐趣&#xff0c;更成为他们自…

C++如何创建一个单例模式的类

单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;其核心目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取这个实例。单例模式通常用于管理共享资源&#xff0c;如配置文件、线程池、缓存等。在C中&#xff0c;创建一个…

yolov8+deepsort+botsort+bytetrack车辆检测和测速系统

结合YOLOv8、DeepSORT、BoTSORT和ByteTrack等技术&#xff0c;可以实现一个高效的车辆检测和测速系统。这样的系统适用于交通监控、智能交通管理系统&#xff08;ITS&#xff09;等领域&#xff0c;能够实时识别并跟踪车辆&#xff0c;并估算其速度。 项目介绍 本项目旨在开发…