小程序性能优化的几点实践技巧

你们好,我叫张文轩,这是个人第6篇分享html

咱们都知道,性能的好坏直接影响用户的体验。本文首先论述下如何评判一个小程序页面的性能状况,以后经过具体的案例重点讲解下几点实践技巧,最后再讲讲key值在渲染一个列表时发挥了一个怎么样的做用,以此来论述为啥key值对性能提高有帮助。chrome

评判小程序页面性能

因为小程序开发环境的特殊性,咱们不能像普通网页那样经过chrome开发工具或者一些成熟的性能测试工具(例如Lighthouse)来了解一个页面的性能,但微信官方提供了一个性能评分的工具,点击这里能够查看工具详情。小程序

体验评分是一项给小程序的体验好坏打分的功能,它会在小程序运行过程当中实时检查,分析出一些可能致使体验很差的地方,而且定位出哪里有问题,以及给出一些优化建议。api

后面我会以一个实际的例子来展现如何经过该工具来优化页面性能,咱们先看下咱们页面优化前的一个评分状况。数组

存在setData的数据过大

咱们的功能里面有个滚动到底部加载的功能,优化前咱们的作法是这样的浏览器

<!--只阐述逻辑,非真实代码-->

// 1: 初始一个list,存储列表数据
data = startList
// 2: 监听滚动事件,滚动到底部获取新数据,并追加到list尾部,最后从新setData
onReachBottom:()=>{
    const {list} = this.data
    fetchNewData().then((res)=>{
        list.push(res.list);
        this.setData({list})
    }
}
复制代码

我估计大部分人面对长列表滚动的时候,一开始的处理方式都是这样的,若是数据很少,只有几页可能不会太暴露问题,若是页数过多,几十页甚至上百页的状况,list的数据会愈来愈大,每次setData的数据就会愈来愈多,于是每次页面从新渲染的节点就会愈来愈多,从而致使滚动到后面,加载愈来愈慢。另外,因为小程序的视图渲染层和数据逻辑处理层是分开的,不是在同一个线程上面的,从用户触发页面交互,处处理数据逻辑,最后层现页面,数据到视图是须要传输的,于是小程序自己对数据大小也有限制,不能超过1M。缓存

setData数据路径

怎么解决呢?小程序setData里面的key支持数据路径的写法,好比bash

let o = obj;
this.setData({
    'o.属性':value
})

或者
let a = array;
this.setData({
    'array[0].text':value
})
复制代码

因此咱们能够经过数据路径的写法,来将数据分批的传输到视图层中,减小一次性setData的数据大小。具体写法以下服务器

// 1.经过一个二维数组来存储数据
let feedList = [[array]];

// 2.维护一个页面变量值,加载完一次数据page++
let page = 1

// 3.页面每次滚动到底部,经过数据路径更新数据
onReachBottom:()=>{
    fetchNewData().then((newVal)=>{
        this.setData({
            ['feedList[' + (page - 1) + ']']: newVal,
        })
    }
}
// 4.最终咱们的数据是[[array1],[array2]]这样的格式,而后经过wx:for遍历渲染数据
复制代码

存在短期内发起太多图片请求(图片懒加载)

这个应该好理解,就是渲染页面时,一次性发送了过多的图片请求,致使了同一时间发起了过多的http请求,http链接是很是耗时的,尤为是一次性发起这么多,而且一次性发起的http连接也是有限制的,好比chrome浏览器就限制一次性最多6个。微信

因此在渲染页面时,不在视图范围内的图片咱们不加载,只有元素出如今视图范围内了,再渲染。

常规的作法是,经过getBoundingClientRect()获取元素的位置,而后与页面滚动位置比较,若是出如今视图内,就将img显示。这种方式有2个问题

  • getBoundingClientRect()方法调用自己容易引发页面重排
  • 监听滚动事件自己就频繁触发,虽然能够经过节流的方式来减小,但仍是容易增长无谓代码处理

IntersectionObserver

其实,微信提供了IntersectionObserver对象。

IntersectionObserver 对象,用于推断某些节点是否能够被用户看见、有多大比例能够被用户看见

经过这个api咱们不用再主动去监听元素位置了,在页面渲染一开始,经过这个api指明须要监听的元素,系统会自动去监听了元素位置。

let data = list;

<img class="img-{{index}}" wx:for="{{data}}"></img>

data.forEach((item,index)=>{
    this.createIntersectionObserver().relativeToViewport.observe(`.img-${index}`,res=>{
        if (res.intersectionRatio > 0){
            this.setData({
                item.imgShow:true
            })
        }
    })
})

复制代码

intersectionRatio值大于0,说明元素出如今视图中了,从新setData数据,显示图片组件。

存在图片太大而显示区域太小

这个问题就是指图片尺寸太大了,而页面上咱们显示的尺寸又过小了,图片尺寸大,请求图片就越慢,致使页面渲染速度降低。

CDN图片处理

对于页面里面的图片,最好都把图片存储在cdn服务器上,一个是能充分利用cdn缓存来加快请求速度,另一个就是cdn上可以将图片进行必定的处理,好比裁剪。我司就是经过cdn来响应图片处理,而后请求图片时告诉cdn服务器须要什么要的尺寸图片,由cdn服务器响应对应尺寸图片。

key值在列表渲染中的做用

key值在列表渲染的时候,可以提高列表渲染性能,为何呢?首先得想一想小程序的页面是如何渲染的,主要分为如下几步:

  1. 将wxml结构的文档构建成一个vdom虚拟数
  2. 页面有新的交互,产生新的vdom数,而后与旧数进行比较,看哪里有变化了,作对应的修改(删除、移动、更新值)等操做
  3. 最后再将vdom渲染成真实的页面结构

key值的做用就在第二步,当数据改变触发渲染层从新渲染的时候,会校订带有 key 的组件,框架会确保他们被从新排序,而不是从新建立,以确保使组件保持自身的状态,而且提升列表渲染时的效率。

key值若是不指明,默认会按数组的索引来处理,于是会致使一些相似input等输入框组件的值出现混乱的问题。

相关测试代码能够查看:wxkey

能够看到

  • 不加key,在数组末尾追加元素,以前已渲染的元素不会从新渲染。但若是是在头部或者中间插入元素,整个list被删除从新渲染,且input组件的值还出现了混乱,值没有正常被更新
  • 添加key,在数组末尾、中间、或者头部插入元素,其它已存在的元素都不会被从新渲染,值也能正常被更新

于是,在作list渲染时,若是list的顺序发生变化时,最好增长key,且不要简单的使用数组索引当作key

最后看看咱们的成果:

体验码:

但愿今天个人分享能对您优化小程序页面有必定的启示,创造出性能更好更流畅的页面。

最后若是喜欢个人文章,欢迎点击关注,我会不按期的分享本身的一些所看所想,和你们一块儿成长,持续学习。

相关文章
相关标签/搜索