小程序之图片懒加载[完美方案,你不来看看?]

效果图

既然来了,把妹子都给你。

image

定义

懒加载,前端人都知道的一种性能优化方式,简单的来说,只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。

实现原理

监听页面的scroll事件,判读元素距离页面的top值是否是小于等于页面的可视高度

判断逻辑代码如下

element.getBoundingClientRect().top <= document.documentElement.clientHeight ? 显示 : 默认

我们知道小程序页面的脚本逻辑是在JsCore中运行,JsCore是一个没有窗口对象的环境,所以不能在脚本中使用window,也无法在脚本中操作组件。

所以关于图片懒加载就需要在数据上面做文章了。

image

页面

页面上面只需要根据数据的某一个字段来判断是否显示图片就可以了,字段为Boolean类型,当为false的时候显示默认图片就行了。

代码大概长成这样

<view wx:for="{{list}}" class='item item-{{index}}'
 wx:key="{{index}}">
    <image class="{{item.show ? 'active': ''}}" src="{{item.show ? item.src : item.def}}"></image>
</view>

布局跟简单,view组件里面有个图片,并循环list,有多少就展示多少

image组件的src字段通过每一项的show来进行绑定,active是加了个透明的过渡

样式

image{
    transition: all .3s ease;
    opacity: 0;
}
.active{
    opacity: 1;
}

逻辑

本位主要讲解懒加载,所以把数据写死在页面上了

数据结构如下:

image

我们使用两种方式来实现懒加载,准备好没有,一起来快乐的撸码吧。

WXML节点信息

小程序支持调用createSelectQuery创建一个SelectorQuery实例,并使用select方法来选择节点,并通过boundingClientRect来获取节点信息。

wx.createSelectorQuery().select('.item').boundingClientRect((ret)=>{
    console.log(ret)
}).exec()
 

显示结果如下

image

悄悄告诉你,小程序里面有个onPageScroll函数,是用来监听页面的滚动的。
还有个getSystemInfo函数,可以获取获取系统信息,里面包含屏幕的高度。

接下来,思路就透彻了吧。还是上面的逻辑, 扒拉扒拉直接写代码就行了,这里只写下主要的逻辑,完整代码请戳文末github

showImg(){
    let group = this.data.group
    let height = this.data.height  // 页面的可视高度
    
    wx.createSelectorQuery().selectAll('.item').boundingClientRect((ret) => {
     ret.forEach((item, index) => {
       if (item.top <= height) { 判断是否在显示范围内
         group[index].show = true // 根据下标改变状态
       }
     })
     this.setData({
       group
     })
    }).exec()

}
onPageScroll(){ // 滚动事件
    this.showImg()
}

至此,我们完成了一个小程序版的图片懒加载,只是思维转变了下,其实并没有改变实现方式。我们来学些新的东西吧。

节点布局相交状态

节点相交状态是啥?它是一个新的API,叫做IntersectionObserver, 本文只讲解简单的使用,了解更多请猛戳没错,就是点我

小程序里面给它的定义是节点布局交叉状态API可用于监听两个或多个组件节点在布局位置上的相交状态。这一组API常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。

里面设计的概念主要有五个,分别为

  • 参照节点:以某参照节点的布局区域作为参照区域,参照节点可以有多个,多个话参照区域取它们的布局区域的交集
  • 目标节点:监听的目标,只能是一个节点
  • 相交区域:目标节点与参照节点的相交区域
  • 相交比例:目标节点与参照节点的相交比例
  • 阈值:可以有多个,默认为[0], 可以理解为交叉比例,例如[0.2, 0.5]

关于它的API有五个,依次如下

1、createIntersectionObserver([this], [options]),见名知意,创建一个IntersectionObserver实例

2、intersectionObserver.relativeTo(selector, [margins]), 指定节点作为参照区域,margins参数可以放大缩小参照区域,可以包含top、left、bottom、right四项

3、intersectionObserver.relativeToViewport([margin]),指定页面显示区域为参照区域

4、intersectionObserver.observer(targetSelector, callback),参数为指定监听的节点和一个回调函数,目标元素的相交状态发生变化时就会触发此函数,callback函数包含一个result,下面再讲

5、intersectionObserver.disconnect() 停止监听,回调函数不会再触发

然后说下callback函数中的result,它包含的字段为

字段名 类型 说明
intersectionRatio Number 相交比例
intersectionRect Object 相交区域的边界,包含 left 、 right 、 top 、 bottom 四项
boundingClientRect Object 目标节点布局区域的边界,包含 left 、 right 、 top 、 bottom 四项
relativeRect Object 参照区域的边界,包含 left 、 right 、 top 、 bottom 四项
time Number 相交检测时的时间戳

我们主要使用intersectionRatio进行判断,当它大于0时说明是相交的也就是可见的。

先来波测试题,请说出下面的函数做了什么,并且log函数会执行几次

1、
wx.createIntersectionObserver().relativeToViewport().observer('.box', (result) => {
    console.log('监听box组件触发的函数')   
 })
 
2、
wx.createIntersectionObserver().relativeTo('.box').observer('.item', (result) => {
    console.log('监听item组件触发的函数') 
})

3、
wx.createIntersectionObserver().relativeToViewport().observer('.box', (result) => {
    if(result.intersectionRatio > 0){
        console.log('.box组件是可见的') 
    }
})

duang,揭晓答案。

第一个以当前页面的视窗监听了.box组件,log会触发两次,一次是进入页面一次是离开页面

第二个以.box节点的布局区域监听了.item组件,log会触发两次,一次是进入页面一次是离开页面

第三个以当前页面的视窗监听了.box组件,log只会在节点可见的时候触发

好了,题也做了,API你也掌握了,相信你已经可以使用IntersectionObserver来实现图片懒加载了吧,主要逻辑如下

let group = this.data.group // 获取图片数组数据
for (let i in this.data.group){   wx.createIntersectionObserver().relativeToViewport().observe('.item-'+ i, (ret) => {
       if (ret.intersectionRatio > 0){
         group[i].show = true 
       }
       this.setData({
         group
       })
     })
}

最后

至此,我们使用两种方式实现了小程序版本的图片懒加载,可以发现,使用IntersectionObserver来实现不要太酸爽。

本文代码请戳github

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容