小程序之圖片懶加載[完美方案,你不來看看?]

效果圖

既然來了,把妹子都給你。javascript

定義

懶加載,前端人都知道的一種性能優化方式,簡單的來講,只有當圖片出如今瀏覽器的可視區域內時,才設置圖片正真的路徑,讓圖片顯示出來。這就是圖片懶加載。html

實現原理

監聽頁面的scroll事件,判讀元素距離頁面的top值是不是小於等於頁面的可視高度前端

判斷邏輯代碼以下java

element.getBoundingClientRect().top <= document.documentElement.clientHeight ? 顯示 : 默認node

咱們知道小程序頁面的腳本邏輯是在JsCore中運行,JsCore是一個沒有窗口對象的環境,因此不能在腳本中使用window,也沒法在腳本中操做組件。git

因此關於圖片懶加載就須要在數據上面作文章了。github

頁面

頁面上面只須要根據數據的某一個字段來判斷是否顯示圖片就能夠了,字段爲Boolean類型,當爲false的時候顯示默認圖片就好了。小程序

代碼大概長成這樣api

<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;
}

複製代碼

邏輯

本位主要講解懶加載,因此把數據寫死在頁面上了

數據結構以下:

咱們使用兩種方式來實現懶加載,準備好沒有,一塊兒來快樂的擼碼吧。

WXML節點信息

小程序支持調用createSelectQuery建立一個SelectorQuery實例,並使用select方法來選擇節點,並經過boundingClientRect來獲取節點信息。

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

顯示結果以下

悄悄告訴你,小程序裏面有個 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有五個,依次以下

一、createIntersectionObserver([this], [options]),見名知意,建立一個IntersectionObserver實例

二、intersectionObserver.relativeTo(selector, [margins]), 指定節點做爲參照區域,margins參數能夠放大縮小參照區域,能夠包含top、left、bottom、right四項

三、intersectionObserver.relativeToViewport([margin]),指定頁面顯示區域爲參照區域

四、intersectionObserver.observer(targetSelector, callback),參數爲指定監聽的節點和一個回調函數,目標元素的相交狀態發生變化時就會觸發此函數,callback函數包含一個result,下面再講

五、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

相關文章
相關標籤/搜索