亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

小程序多圖列表實現(xiàn)性能優(yōu)化的方法步驟

 更新時間:2019年05月28日 11:34:30   作者:ssthouse  
這篇文章主要介紹了小程序多圖列表實現(xiàn)性能優(yōu)化的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

寫這篇文章的緣由: 最近在公司的小程序項目中遇到了頁面圖片元素過多導致的性能問題. 從小程序提供的性能檢測面板分析, 確定是圖片元素占用了過多內存導致.

因為本人之前主要是做桌面端應用開發(fā)和原生app開發(fā), 沒有太顧及過移動端圖片的內存占用問題. 這次既然遇到了, 也就趁這個機會學習一下其優(yōu)化的技巧.

什么造成的性能問題

簡單的來說: DOM節(jié)點過多 && 圖片節(jié)點過多

DOM節(jié)點過多會造成更多的內存占用. 按照目前的微信小程序限制, 內存占用500M以上會出現(xiàn)卡頓, 甚至閃退. 如果列表中節(jié)點沒有圖片標簽, 內存占用現(xiàn)象還不會太明顯, 只是DOM節(jié)點過多會造成頁面渲染耗時增加. 但當列表節(jié)點中含有圖片時, 內存占用會迅速攀升.

如何解決這兩點呢?

對于上面兩點, 我們分別有對應的優(yōu)化思路

1. DOM節(jié)點過多.

對于無限加載的頁面, 列表中每一個元素都有大量的子節(jié)點. 當列表數(shù)目增加時, 頁面的總節(jié)點數(shù)會暴增. 以小紅書的小程序為例:

上圖中可以看到, 該頁面為很多的卡片組成的列表頁面. 假設一個卡片的DOM子節(jié)點數(shù)為 30, 那么當列表元素加載到1000時, 頁面會有 30 * 1000 = 30,000 個DOM節(jié)點. 小程序顯然是吃不消的 (注: 微信小程序推薦總節(jié)點數(shù)不超過: 1000)

那我們該如何處理來減少節(jié)點數(shù)呢?

思路很簡單: 我們可以只對用戶當前屏幕和上下兩屏進行真實內容的加載, 對于其他用戶暫時不可見的地方, 用空白的節(jié)點進行占位. 這樣處理后, 實際有內容的卡片數(shù)目不超過5個, 頁面的總節(jié)點數(shù)為: 5 * 30 + 995 = 1145. 相對于之前的節(jié)點數(shù)有了巨大的改進.

讓我們來看看代碼的實現(xiàn)

寫代碼前, 讓我們整理一下需要的數(shù)據(jù)結構.

首先這是一個列表頁面, 我們需要一個 List來保存頁面顯示的數(shù)據(jù): showCards. showCards 中只會保存5條真實數(shù)據(jù), 其余數(shù)據(jù)展示以空對象填充.

我們還需要一個保存所有真實數(shù)據(jù)的List, 這樣當用戶滑動頁面時, 我們才能實時獲取需要顯示的卡片真實數(shù)據(jù): totalCards

Page({
 showCards: [],
 totalCards: []
})

接下來我們來寫頁面布局部分:

<view wx:for="{{showCards}}"
    wx:key="{{index}}">

  <self-define-component data-card-data="{{item}}">
  </self-define-component>
  
</view>

簡單的代碼框架就是這樣 (這里省略了很多不影響理解思路的代碼細節(jié))

我們先實現(xiàn)沒有優(yōu)化DOM節(jié)點的代碼邏輯. 在頁面滑動到最底部時, 向showCards push進新的卡片, 并通過 setData 更新頁面. 這樣就實現(xiàn)了一個簡單的下拉無限加載的列表頁面.

async onReachBottom() {
  const newCards = await fetchNewCards();
 this.data.showCards.push(newCards);
 this.setData({
  showCards: this.data.showCards
 })
},

接下來我們實現(xiàn)優(yōu)化DOM節(jié)點的代碼邏輯. 我們會再用戶滑動頁面(onScroll事件) 時, 對當前頁面每個card 的位置進行判斷, 如果該 card在用戶可見范圍內的上下兩屏內, 則展示真實數(shù)據(jù), 否則將其替換為寬高與原卡片一致的空白占位節(jié)點.

在 Page 的 onPageScroll 回調中, 我們進行回收函數(shù)的調用 (注意這里回調時要進行節(jié)流處理, 否則頻繁調用會導致頁面閃動) . 讓我們看看這個回收頁面節(jié)點函數(shù)的主要邏輯:

回調中, 我們首先通過小程序提供的獲取頁面元素位置的api: createSelectorQuery().boundingClientRect 來拿到每個卡片的位置信息.

接下來, 我們通過位置信息, 判斷是否展示card的真實數(shù)據(jù). 對于不展示真實數(shù)據(jù)的card, 我們需要保存其高度信息, 以便在渲染頁面時使用高度信息填充頁面. 同時我們給空card一個 type 屬性, 方便我們在 wxml中渲染時判斷卡片類型.

async onScrollCallback() {
 try {
  const rectList = await this.calcCardsHeight();
  this.recycleCard(rectList);
 } catch (e) {
  console.error(e);
 }
}
 calcFeedHeight() {
  return new Promise((resolve, reject) => {
   this.createSelectorQuery()
    .selectAll(`.card`)
    .boundingClientRect(rectList => {
     resolve(rectList);
    })
    .exec()
  })
 },

 recycleCard(rectList) {
  const newShowCards = [];
  for (let i = 0; i < this.data.showCards.length; i++) {
   const rect = rectList[i];
   if (rect && Math.abs(rectList[i].top - 0) > pageHeight * 2) {
    newShowCards.push({
     type: 'empty-card',
     height: rectList[i].bottom - rectList[i].top
    });
   } else {
     const feed = totalCards[i];
    newShowCards.push(feed);
   }
  }
  this.setData({
   showCards: newShowCards
  });
 }

接下來, 我們要對wxml布局文件進行相應的修改:

 <view wx:for="{{showCards}}"
    wx:key="{{index}}">

  <view wx:if="{{item.type === 'empty-card'}}"
     class="card empty-card"
     style="height: {{item.height}}px">
  </view>

  <self-define-component wx:if="{{item.type !== 'empty-card'}}"
        data-card-data="{{item}}"
        class="card read-card">
  </self-define-component>
  
 </view>

這樣, 我們就解決了 DOM節(jié)點數(shù)目過多的問題. 并且最大限度的不影響用戶的體驗. (雖然用戶快速上下滑動時還是會看到一些空白, 但大多數(shù)情況用戶不會非常快速的上下滑, 而是閱讀內容并慢速滑動)

2. 圖片節(jié)點過多

通過上面一步的優(yōu)化, 我們其實已經(jīng)大幅減少了頁面加載的圖片數(shù)目. 但是有些情況, 我們的列表中的每一個卡片并不是只有一張圖, 有時我們的圖片組件是一個 swiper. 我們假設每個swiper平均展示10張圖片, 那么我們展示5張card的話,<Image/> 節(jié)點就有 50 個. 對于一些低端的安卓機, 這樣的開銷依然會造成卡頓.

那有什么好的優(yōu)化方案呢? 前面一個問題, 我們的優(yōu)化思路是在用戶看不見的地方, 將節(jié)點簡化展示.

同樣的, 對于swiper控件, 用戶能看到的也就是當前圖片 以及 滑動可見的左右兩張圖片. 其余位置的圖片是可以簡化展示的. 從下圖可以看到, 其實需要立即加載的圖片只有三張. (紅色的框代表的是swiper組件的可視區(qū)域)

我們使用一個變量記錄當前swiper控件展示圖片的坐標: curIndex, 然后我們改造一下 wxml布局文件. 代碼邏輯很簡單, 就是通過判斷當前Image 節(jié)點的index和swiper展示節(jié)點的 index之間距離, 大于2就不顯示.

經(jīng)過這樣的處理后, 我們的每個swiper組件, 最多只會有三個占用實際內存的 <Image/> 節(jié)點.

   <swiper-item wx:for="{{images}}"
          wx:key="{{index}}">

    <view >
     <image class="img"
         mode="widthFix"
         src="{{index - curIndex < 2 && index - curIndex > -2 ? item.url : ''}}">
     </image>
    </view>
   </swiper-item>

最后

以上就是我在這次性能優(yōu)化中用到的一些小技巧, 希望能為你帶來一些幫助 :)

如果你對我的文章感興趣, 這里有我的一些 數(shù)據(jù)可視化, D3.js 方面的文章, 歡迎 fork && star:

https://github.com/ssthouse/ssthouse-blog

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論