溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

小程序瀑布流組件怎么實現(xiàn)翻頁與圖片懶加載

發(fā)布時間:2020-07-23 14:29:16 來源:億速云 閱讀:406 作者:小豬 欄目:web開發(fā)

小編這次要給大家分享的是小程序瀑布流組件怎么實現(xiàn)翻頁與圖片懶加載,文章內容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

電商小程序中,用到瀑布流的地方非常多,每次都寫一個瀑布流,重復一次邏輯,作為程序員,肯定是非常不愿意的。
瀑布流的形式都是大同小異,不同的是瀑布流中每個模塊的內容,隨業(yè)務而變化。
所以,我們把瀑布流框架抽象成組件,瀑布流的內容由業(yè)務確定。這樣即可實現(xiàn)組件化和自定義的最大平衡,微信小程序組件源碼。

首先,我們來看一下瀑布流組件在實際項目中的實際效果。

1 實際效果

瀑布流組件實際效果如下圖所示,左側為用戶交互效果,右側為圖片懶加載實際效果。

小程序瀑布流組件怎么實現(xiàn)翻頁與圖片懶加載

2 什么是瀑布流?

瀑布流,又稱瀑布流式布局。是比較流行的一種網(wǎng)站頁面布局,waterfall-item寬度固定,高度不定,視覺表現(xiàn)為參差不齊的多欄布局,隨著頁面滾動條向下滾動,這種布局還會不斷加載數(shù)據(jù)塊并附加至當前尾部。如下圖所示:

小程序瀑布流組件怎么實現(xiàn)翻頁與圖片懶加載

3 實現(xiàn)功能

該瀑布流組件實現(xiàn)了以下幾個功能:

  • 支持圖片懶加載
  • 支持上拉數(shù)據(jù)翻頁
  • 支持自定義樣式
  • 支持瀑布流Item間隔底層自動計算
  • 原生組件模式:即類swiper和swiper-item 組件用法
  • 組件與數(shù)據(jù)完全解耦

4 實現(xiàn)原理

4.1 waterfall 和waterfall-item實現(xiàn)原理

第一步:在 waterfall-layout 目錄下創(chuàng)建 waterfallwaterfall-item 組件,目錄結構如下:

.
├── query-node.js
├── waterfall-item.js
├── waterfall-item.json
├── waterfall-item.wxml
├── waterfall-item.wxss
├── waterfall.js
├── waterfall.json
├── waterfall.wxml
└── waterfall.wxss

第二步:分別在waterfall.jswaterfall-item.jsrelations選項中指定組件父、子級關系:

// waterfall.js
Component({
 // ... other code
 relations: {
 './waterfall-item': {
  type: 'child',
 },
 // ... other code
 }
})
// waterfall-item.js
Component({
 // ... other code
 relations: {
 '././waterfall': {
  type: 'parent',
 },
 // ... other code
 }
})

指定彼此的父、子組件的關系后,即可通過 this.getRelationNodes 原生 API,就能訪問彼此實例對象及其屬性和方法。

第三步:實現(xiàn)waterfall.wxmlwaterfall-item.wxml代碼:
waterfall.wxml代碼實現(xiàn)非常簡單,只有5行代碼:

<view class="waterfall custom-class">
 <view class="waterfall-inner">
 <slot ></slot>
 </view>
</view>

同樣,waterfall-item.wxml代碼實現(xiàn)也非常簡單,只有5行代碼:

<view
 class="waterfall-item custom-class"
 
>
 <slot ></slot>
</view>

不知道slot用法的童鞋,請參考微信小程序自定義組件模板和樣式文檔。

4.2 瀑布流原理

其實,不管是微信小程序、web、還是原生APP,瀑布流的實現(xiàn)原理都是一樣的。都可以絕對定位和位置計算來實現(xiàn)。
瀑布流的大體過程如下圖所示:

第一步:數(shù)據(jù)通過this.setData從邏輯層傳輸?shù)揭晥D層,進行第一渲染,由于每個waterfall-itemtop:0;position:left;,所以都重疊了在一起。

第二步:通過節(jié)點查詢API獲取每個waterfall-item元素信息,并且計算出正確的topposition值。

第三步:setData每個waterfall-itemtopposition,實現(xiàn)重排。

小程序瀑布流組件怎么實現(xiàn)翻頁與圖片懶加載

具體邏輯實現(xiàn)如下:

首先,我們來實現(xiàn)一個節(jié)點查詢API querySelector,之后會用到:

// query-node.js
/**
 * 獲取當前頁面中,選擇器為 selector 的第一個node節(jié)點
 * @param {String} selector 符合微信小程序規(guī)范的選擇器
 * @param {Object} context 調用環(huán)境,普通頁面中為wx,自定義組件中為this;默認值為wx.
 * @return {Array} 返回一個數(shù)組,第一個元素為 node 節(jié)點
 */
export const querySelector = function (selector, context = wx) {
 return new Promise((resolve, reject) => {
 context.createSelectorQuery()
 .select(selector)
 .boundingClientRect((res) => {
  if (res) {
  resolve(res);
  } else {
  reject(`不存在選擇器為 ${selector} 的節(jié)點`);
  }
 })
 .exec();
 })
};

接著,看一下組件waterfallwaterfall-item在實際項目中的用法:

 <waterfall
  loading="{{loadMorePending}}"
  isAllLoaded="{{isAllLoaded}}"
 >
  <block wx:for="{{data.sections}}" wx:key="id" wx:for-item="product">
  <waterfall-item
   index="{{index}}"
   custom-class="flow-item-wrapper"
  >
   <view class="product-item">
   業(yè)務代碼
   </view>
  </waterfall-item>
  </block>
 </waterfall>

當?shù)谝粋€waterfall-item組件,在視圖層布局完成后會執(zhí)行ready生命周期鉤子。
ready 生命周期鉤子中,我們需要做兩件事:

  • 獲取父組件waterfall的實例對象,并掛載在waterfall-item組件的 this實例對象上。因為之后我們需要在waterfall-item組件中修改waterfall上的數(shù)據(jù)。
  • 獲取waterfall-item組件的高度,計算waterfall-item組件的位置信息topposition。
// waterfall-item.js
import { querySelector } from './query-node';
Component({
 // ... other code
 lifetimes: {
 ready() {
  const [waterfall] = this.getRelationNodes('./waterfall');
  this.parent = waterfall;
  this.setWaterfallItemPosition();
 },
 }
 methods:{
 async setWaterfallItemPosition() {
  querySelector('.waterfall-item', this)
  .then(async (node) => {
   const { top, position } = await this.parent.getWaterfallItemPostionInfo(node);
   this.setData({
   top,
   position
   })
  })
 }, 
 }
 // ... other code
})

setWaterfallItemPosition方法中,我們調用了父組件上的方法this.parent.getWaterfallItemPostionInfo,獲取當前waterfall-item組件的topposition信息。并把已經(jīng)渲染好的waterfall-item組件的累計高度緩存在waterfallleftHeightsrightHeights屬性上,用于計算下一個waterfall-item組件位置,主要邏輯如下:

// waterfall.js
const POSITION_LEFT = 'left';
const POSITION_RIGHT = 'right';

Component({
 // ... other code
 /**
 * 組件的方法列表
 */
 methods: {
 lifetimes: {
  ready() {
  this.initParams();
  }
  },
 initParams() {
  this.leftHeights = 0;
  this.rightHeights = 0;
 },
 /**
  * 設置 waterfall-item 的高度值
  * @param {Object} node waterfall-item 組件位置尺寸數(shù)據(jù)
  */
 async getWaterfallItemPostionInfo(node) {
  let top = 0;
  let position = POSITION_LEFT;
  const { height } = node;
  const { itemGap } = this;
  if (this.leftHeights <= this.rightHeights) {
  top = this.leftHeights;
  if(this.leftHeights === 0) {
   this.leftHeights += height;
  } else {
   top += itemGap;
   this.leftHeights += (height + itemGap);
  }
  } else {
  position = POSITION_RIGHT;
  top = this.rightHeights;
  if(this.rightHeights === 0) {
   this.rightHeights += height;
  } else {
   top += itemGap;
   this.rightHeights += (height + itemGap);
  }
  }
  return {
  top,
  position,
  }
 }
 // ... other code
 }
})

當所有的waterfall-item重排結束后,瀑布流渲染完成。

4.3 圖片懶加載原理

微信小程序中,<image>標簽本身是支持懶加載的,當lazy-load={{true}},且在即將進入一定范圍(上下三屏)時才開始加載。

也就是說,當lazy-load={{true}},<image>標簽初次渲染在視口上下三屏之外時,是不會請求圖片資源的,當<image>即將進入三屏之內時,才會加載。

在4.2小節(jié)的圖3中,<waterfall-item>的初始化位置設置成了top:0;position:left;,所以,都在視口中。如果將top的值成三屏之外的數(shù)值,例如,400vh或者更大,則<waterfall-item>重排之后,任然在三屏之外的圖片即會自動懶加載。

<view
 class="waterfall-item custom-class"
 
>
 <slot ></slot>
</view>
Component({
 // waterfall-item.js
 // ... other code
 lifetimes: {
 ready() {
  const { itemCount } = this.data;
  const [waterfall] = this.getRelationNodes('./waterfall');
  waterfall.childCount += 1;
  this.parent = waterfall;
  this.setData({
  itemCount: itemCount + waterfall.childCount,
  })
 },
 },
 // ... other code
})

4.4 數(shù)據(jù)翻頁

因為實現(xiàn)了wx:for <waterfall-item>功能,和<swiper-item>組件一樣,因此翻頁邏輯完全由用戶自己定制,<waterfall><waterfall-item>只給你提供翻頁的功能,組件就可以和瀑布流數(shù)據(jù)結構完全解耦。

4.5 瀑布流Item間隔底層自動計算

將列和行中,兩個<waterfall-item>組件之間的距離定義為itemGap,則:

itemGap = waterfall寬度 - (waterfall-item寬度 * 2)

<waterfall>ready鉤子中,可以獲取到<waterfall>組件的寬度;同理,在<waterfall-item>ready鉤子中,可以獲取到<waterfall-item>組件的寬度。
在調用getWaterfallItemPostionInfo之前,獲取到itemGap的值即可。這樣,在計算<waterfall-item>top值時,除了第一行的<waterfall-item>top值等于0之外,其他所有<waterfall-item>top值等于:

// this.leftHeights += height + itemGap;
// or 
// this.rightHeights += height + itemGap;

具體代碼實現(xiàn)請查看源碼

5 總結

通過瀑布流框架抽象,使<waterfall><waterfall-item>接近原生組件使用體驗,同時使組件與數(shù)據(jù)完全解耦。通過巧妙的初始化位置top設置,使瀑布流具圖片有懶加載的功能。

看完這篇關于小程序瀑布流組件怎么實現(xiàn)翻頁與圖片懶加載的文章,如果覺得文章內容寫得不錯的話,可以把它分享出去給更多人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI