实践总结小程序性能优化

微信小程序开发教程栏目总结小程序的性能优化。

项目简述 & 问题

先简单介绍一下项目,就是一个比较常规的点餐小程序。

界面如图:

左边是分类菜单,右边是长列表,有多个分类的商品,单个分类滚动完后可以继续滚动切换到下一个分类,同时左边的分类菜单选中态会跟着切换到当前商品列表显示的分类。

考虑到更好的用户体验,以及参考了美团等点餐小程序,这个商品列表的数据是一次性返回的。目前遇到的问题就是,当商品数量比较多时,首次渲染时间很长,而且页面会卡顿。

优化方向

逻辑优化

小声bb:其实就是原来代码(由于历史原因)写得太烂了……OTL

先放个图

小声bb:连小程序都看不下去了,要警告了

微信开发者工具都有警告了,而且提示里面也有定位到具体代码的位置,所以关键就是这个 setData !!!

我们可以先看看官方对于小程序性能以及 setData 优化的一些建议。(developers.weixin.qq.com/miniprogram…)

具体实践:

1. setData 不能一次性传太多数据,如果列表太长,可以分开渲染【比如转化为二维数组,每次循环渲染一个数组】。

v1:简单粗暴版

// 每次渲染一个分类// 假设goodsList是一个二维数组goodsList.forEach((item, index) => {    this.setData({
        [`goodsList[${index}]`]: item
    })
})复制代码

像上面这样写会有一个问题,页面首屏渲染是快了,但是点击页面操作(比如加购按钮等),页面会卡住,等一下才有反应,操作反馈延迟严重。

其实这是因为,这个循环是把单次 setData 数量减少了,但是却变成了循环多次 setData,我们看着首屏显示好了,但是其实其他分类(其他数组)还在渲染,线程还是忙碌状态,JS 线程一直在编译执行渲染,点击事件不能及时传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层。

v2:定时器hack版

既然js线程忙着渲染,那我们可以强制让它先停下来。于是有了v2的定时器hack版。

// 每次渲染一个分类let len = data.goodsList ? data.goodsList.length : 0;let idx = 0let timer = setInterval(() => {    if (idx < len) {
        that.setData({
            [`goodsList[${idx}]`]: data.goodsList[idx]
        });
        idx++
    } else {        clearInterval(timer)
    }
}, 15);复制代码

现在首屏渲染速度问题解决了,点击按钮延迟响应问题也解决了。就是代码有点hack,逼死强迫症

v3:大杀器——虚拟列表

虚拟列表简单说原理就是只渲染当前显示屏幕区域以及前n屏和后n屏的数据,用一个单独的字段保存当前需要显示的数组(就是当前一屏+前n屏+后n屏),每次列表滚动的时候重新计算需要显示的数据,更新这个字段,页面就会相应更新了。这样就能保证页面上的元素节点数量不会太多,就可以支持大量数据的长列表需求。

更详细的原理和实现各位同学们可以自己搜一下,此处不展开。

小程序官方也有开源的虚拟列表组件:recycle-view

2. setData 可以支持颗粒更新,指定到具体的属性。

比如加购等操作,需要更新商品右上角的小数字,可以这样写:

this.setData({
    [`goodsList[${categoryIndex}][${goodsIndex}].num`]: goodsItem.num
})复制代码

3. 跟页面无关的数据不要保存在 data,不要用 setData 更新,因为 setData 会触发页面渲染。

eg:

Page({    data: {
        ...
    },    // 跟页面渲染无关的数据
    state: {        hasLogin: false,
    },
    ...
})// 更新的时候直接赋值就行this.state.hasLogin = true复制代码

PS:或者甚至不需要挂载到 page 对象下,直接用普通变量保存。

4. 图片大小优化

在长列表中图片大小如果不加限制,大量的大图会占用很多内存,有可能导致iOS客户端内存占用上升,从而触发系统回收小程序页面。除了内存问题外,大图片也会造成页面切换的卡顿。

解决办法就是根据当前显示的图片区域大小,取尺寸刚好合适(2倍-3倍图)的图片。

建议图片用CDN,一般CDN服务厂商提供图片服务的都会提供裁剪图片的接口,然后接口只返回原图链接,前端根据需要传参数裁剪图片。前端具体做法可以写公共的图片处理方法,或者自己封装图片组件。

附常用图片CDN服务商图片裁剪API文档:

  • 阿里云OSS图片缩放
  • 七牛云图片处理

5. 减少不必要的数据请求

比如在该点餐页面进入时需要获取定位,然后根据定位获取最近的门店,前面两个接口都需要请求(具体可以根据业务需求),而最后如果获取到的距离最近的门店跟上次一样,则不需要重新获取店铺详情和商品数据。

体验优化

1. 合并短时间内的多个loading提示

还是该点餐页面流程,像上文说过的,进入页面时需要获取定位接口,等定位接口返回结果了再拿定位取值去获取距离最近的店铺,最后才是请求店铺和商品数据。

这三个接口是串行的。此时如果我们每个接口都弹出一个loading提示,就会出现loading显示一会儿,消失,又显示一会儿,又消失……这样的现象,这样的体验是不太好的。

建议可以通过封装请求,并且在请求里统一处理loading,来合并短时间内多次发起请求的多个loading。

eg:

let showLoadingTimer = null;let showRequestLoading = false; // 标记是否正在显示loading/**
 * 封装request
 * @param {*} {showLoading:是否需要显示loading, options:request参数,如url,data等} 
 */function request({showLoading = true, ...options}) {    // 显示request loading
    handleShowLoading(showLoading)

    wx.request({
        ...        complete() {            // 关闭request loading
            handleShowLoading(false)
        }
    })
}/**
 * 封装request loading
 * 短时间内如果调用多次showLoading,会合并在一起显示,而不是每个都闪现一下
 * @param showLoading
 */function handleShowLoading(showLoading) {    if (showLoading) {        // 显示loading
        clearTimeout(showLoadingTimer);        if (!showRequestLoading) {
            showRequestLoading = true;
            wx.showNavigationBarLoading();
            wx.showLoading({ title: "加载中", mask: true })
        }
    } else {        // 200ms后关闭loading
        showLoadingTimer = setTimeout(() => {
            showRequestLoading = false;
            wx.hideNavigationBarLoading();
            wx.hideLoading()
        }, 200)
    }
}复制代码

2. 整个页面初次加载时可以使用页面loading动画或骨架屏,优化加载中体验。

3. 静默获取、更新数据

比如这个点餐页每次 onShow 都会调用定位接口和获取最近门店接口,但是不显示loading,用户就没有感知,体验比较好。

接口优化

需要关注接口的粒度控制。 因为有时候合并接口,前端可以减少一次请求,体验更好;但有时候如果接口的数据太多,响应太慢,就可以考虑是否某部分数据可以后置获取,让主要的页面内容先渲染出来,根据这个设计来拆分接口。

比如项目中的点餐页面,原来购物车数据和商品规格弹窗显示的详情数据都是在获取店铺商品接口一次性返回的,而这个接口本来由于设计需要一次返回所有商品,就会造成数据量太大,而且后端需要查询的表也更多。于是把获取购物车,和商品详情接口都拆分为单独的接口,获取店铺商品接口的响应时间就减少了,页面也能更快显示出来。

总结

其实上面提到的逻辑优化和接口优化很多都是细节,并不是太高深的技术,我们平时迭代的时候就可以注意。而体验方面的优化则需要前端同学在前端技术以外更多关注用户体验和设计方面的知识啦,而且这也是一个有追求的前端应该具备的技能……←_←

所以嘛……技术路漫漫,大家共勉吧

相关免费学习推荐:微信小程序开发教程

以上就是实践总结小程序性能优化的详细内容,更多请关注编程之家其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


概述 消息能力是小程序能力中的重要组成,我们为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。 订阅消息推送位置:服务通知 订阅消息下发条件:用户自主订阅 订阅消息卡片跳转能力:点击查看详情可提爱转至该小程序的页面 消息类型 一次性订阅消息 一次性订阅消息用于解决用户使用小程序后,后续服务
判断H5页面环境在微信中还是小程序中 用小程序提供的wx.miniProgram.getEnv可以获取环境参数 &lt;script type=&quot;text/javascript&quot; src=&quot;https://res.wx.qq.com/open/js/jweixin-1.
wx.reLaunch和wx.navigateTo,wx.navigateTo的区别 2019-03-23 11:18:05 wx.navigateTo 用于保留当前页面、跳转到应用内的某个页面,使用 wx.navigateBack可以返回到原页面。对于页面不是特别多的小程序,通常推荐使用 wx.n
微信小程序如何从数组里取值_微信小程序 传值取值的几种方法总结 小程序里常见的取值有以下几种,一个完整的项目写下来,用到的概率几乎是100%。 列表index下标取值 页面传值 form表单取值 1. 列表index下标取值 实现方式是:data-index=&quot;{{index}}&quot
H5项目接入微信授权登录,通过 UA 区分微信还是普通浏览器: let&#160;ua&#160;=&#160;navigator.userAgent.toLowerCase(); let&#160;isWeixin&#160;=&#160;ua.indexOf(&#39;micromessenge
微信小程序获取data-xx=&quot;&quot;属性的值,自定义属性设置和获取(data-) 微信小程序&lt;view class=&quot;details-btn&quot; data-taskId=&quot;111&quot; bindtap=&#39;taskdetails&#39
小程序报错:TypeError: Cannot read property ‘addEventListener‘ of undefined 解决办法 将调试基础库由2.16.0(或者当前的) -&gt; 2.14.1 解决问题
H5跳转微信小程序-成功案例(VUE)(踩坑无数) TuoMei 已于 2022-07-29 09:52:22 修改 准备工作 根据官方提供的资料需准备以下几点: 1、已认证的服务号 2、绑定JS接口安全域名 (在微信公众平台设置) 3、IP白名单 (在微信公众平台设置) 4、将小程序和H5公众号进
微信小程序 页面跳转和数据传递实例详解 这篇文章主要介绍了微信小程序 页面跳转和数据传递实例详解的相关资料,这里附有实例代码帮助到家学习理解,需要的朋友可以参考下 微信小程序 页面跳转和数据传递 1.先导 在Android中,我们Activity和Fragment都有栈的概念在里面,微信小程序页面也
情景1.拉取公司代码演示: 因为github有墙,这里我们以gitee(码云)为例作为演示 (其实就是国产github,也非常好用~) 步骤一:打开Git界面 先在一个空文件夹右击Git Bash Here,打开git界面 步骤二:输入克隆远程仓库指令 别人复制的链接在这里获取 拿到别人赋值的链接自
如何开发微信小程序? 作为一名10多年一直从事互联网平台开发的从业者,我来回答下这个问题吧。 微信小程序开发流程总体可以归纳为4个步骤, 老张带您捋一捋整个环节,小白用户可以收藏了。 好了废话不多说,开始! 一、开发前小程序需要准备的资料 我们在开发微信小程序前,需要准备下相关资料。这个资料主要是后
原生小程序开发优化方案 为了更好的制定优化方案,我们 有必要先了解下小程序的底层架构、以及与普通网页开发的差异 小程序最终渲染载体与当下一些热门的技术 Flutter、React Native等不同,依然是浏览器内核,而不是原生客户端。 而对于传统的网页来说,UI 渲染和 JS 脚本是在同一个线程中
1,不要下两倍尺寸的图片, 小程序本身自己就会对元素缩小两倍,设计图片的一杯就已经很清晰了。 2,图片压缩,(主要是压缩静态资源,ps 可以压缩,然后有一些在线压缩工具,保持600-800kb 的静态) 3,通用的代码组件化 4,是在工程量太大可以分包,分包现在最大支持20m(一般都不会去分包的)
文章浏览阅读189次。人工智能研究实验室OpenAI在2022年11月30日发布了自然语言生成模型ChatGPT,上线两个月就已经超过一亿用户,成为了人工智能界当之无愧的超级大网红。ChatGPT凭借着自身强大的拟人化及时应答能力迅速破圈,引起了各行各业的热烈讨论。简单来说ChatGPT就是可以基于用户文本输入自动生成回答的人工智能聊天机器人。那肯定会有人说这不就是Siri嘛,虽然都是交互机器人但是两者的差别可老大了。那么ChatGPT在人机交互时为什么会有这么出色的表现?它到底会不会取代搜索引擎?90%的人真的会因为ChatG
文章浏览阅读193次。8. 导航和路由管理:掌握小程序的导航方式,如使用wx.navigateTo跳转页面、使用wx.redirect重定向页面等,学会实现页面之间的跳转和传参。1. 小程序的基本概念和架构:了解小程序的定义、特点以及与传统APP的区别,掌握小程序的运行环境、组件和API等基本概念。10. 支付功能:学习小程序的支付方式,如微信支付、支付宝支付等,了解支付流程和注意事项,学会实现小程序的支付功能。9. 用户授权和登录:了解小程序的用户授权机制,如获取用户信息、调用微信API等,学会实现用户的登录和注册功能。_微信小程序开发知识点总结
文章浏览阅读4.8k次,点赞7次,收藏18次。一、准备工作1. 安装微信开发者工具,并登录微信小程序账号;2. 准备斗地主游戏的图片资源;3. 准备斗地主游戏的音效资源;二、创建小程序1. 打开微信开发者工具,点击“新建小程序”,输入小程序名称,选择小程序的项目目录,点击“创建”;2. 在小程序的项目目录中,新建文件夹“images”,将准备好的斗地主游戏的图片资源放入“images”文件夹中;3. 在小程序的项目目录中,新建文件夹“sounds”,将准备好的斗地主游戏的音效资源放入“sounds”文件夹中;三、编写代码1. 在小程_扑克牌微信小程序代码
文章浏览阅读3.9k次,点赞3次,收藏7次。一、准备工作:1. 安装微信开发者工具,创建小程序项目;2. 准备游戏角色图片;3. 准备游戏背景音乐;二、实现步骤:1. 创建游戏页面,添加游戏角色图片,添加游戏背景音乐;2. 创建游戏角色类,定义游戏角色属性,如角色名称、角色图片、角色能力等;3. 创建游戏类,定义游戏属性,如游戏人数、游戏角色、游戏规则等;4. 创建游戏控制类,定义游戏流程,如游戏开始、游戏结束、游戏角色分配等;5. 创建游戏界面,实现游戏流程,如游戏开始、游戏结束、游戏角色分配等;6. 创建游戏结果页面,显示游戏_微信小程序游戏代码
文章浏览阅读1.7k次。1. 创建小程序项目:使用微信开发者工具创建一个小程序项目,并在项目中添加一个页面,用于模拟聊天。 2. 定义数据结构:定义一个数据结构,用于存储聊天记录,包括发送者、接收者、消息内容等信息。 3. 实现聊天功能:实现聊天功能,包括发送消息、接收消息、显示消息等功能。 4. 实现界面:使用微信小程序的界面框架,实现聊天界面,包括聊天记录列表、输入框等。代码示例:// 定义数据结构var chatData = { sender: '', receiver: '', message: '' };_制作聊天对话小程序代码
文章浏览阅读2.1k次。1、创建小程序项目:使用微信开发者工具,新建一个小程序项目,输入项目名称,选择项目目录,点击“创建”按钮,即可创建小程序项目。2、添加页面:在小程序项目中,可以添加多个页面,每个页面都有自己的页面文件,比如首页、分类页、购物车页、我的页面等。3、添加组件:在小程序项目中,可以添加多个组件,比如商品列表组件、购物车组件、订单组件等,用于在页面中显示商品信息、购物车信息、订单信息等。4、添加接口:在小程序项目中,可以添加多个接口,用于获取商品信息、购物车信息、订单信息等,以便在页面中显示。5、_微信开发者工具做一个我的商城