Mark Ku's Blog
首頁 關於我
解決前端渲染大量資料渲染效能問題 Part's 2- 虛擬捲軸 && 分段渲染
Frontend
解決前端渲染大量資料渲染效能問題 Part's 2- 虛擬捲軸 && 分段渲染
Mark Ku
Mark Ku
April 16, 2020
1 min

定義問題

先前有對大資料渲染進行調察研究,得知瞬間大資料的渲染,會造成瀏覽器卡頓不回應,並得出可以透過分時渲染、捲動式渲染、虛擬列表,解決高併發渲染的問題。

而籃足球比賽比分列表,一遇假日就會有1000~2000 筆的比賽需要同時顯示,且依使用者需求,不能分頁顯示。

虛擬捲軸 VS 分段渲染

虛擬捲軸概念

設計概念,一開始先傳入高度,並將每一筆 item 的 邊界 getBoundingClientRect 結果快取起來,直到渲染出來會重新計算快取高度,透過容器的卷軸事件,css translate3d,操作 y 軸,達到到平移捲動的效果,只有利用實體捲軸的高度及捲動事件,但不是透過實體捲軸顯示,因此這就是為什麼稱之虛擬捲軸的原因。

分段渲染概念

跟虛擬捲軸最大的差異,分段捲軸一開始採用的用的真實的實體捲軸,除buffer item 其餘都僅渲染空 div 支撐捲軸高度,直到捲到 buffer item 時,才開始渲染該區間的元件。

和傳統渲染效能比較

拿 1000 筆左右的數據,資料採用分段渲染和一般炫染效能做比較,因為要渲染的筆數少了,其實可以預期效能差了快1x倍之多。

一般渲染

分段渲染

使用方式

虛擬捲軸

<VirtualScroller
      :list="news"
      class="news-list-wrapper"

      :item-default-height="100"
      :uni-key="'id'"
      :enable-scroll-up="!isLastPage"
      :auto-load-more="true"
      :enable-scroll-down="true"
      :buffer-size="4"
      @scrollDown="scrollDown"
      @scrollUp="scrollUp"
    >
      <template #default="slotScope">
        <NewsCard
          :id="'news-' + slotScope.item[slotScope.uniKey]"
          :key="'news-' + slotScope.item[slotScope.uniKey]"
          :start="slotScope.start"
          :end="slotScope.end"
          :index="slotScope.index"
          :h="slotScope.height"
          :news="slotScope.item"
          :sport-id="slotScope.item.sportId"
        />
      </template>
</VirtualScroller>

分段捲軸

<PartRenderingScroller :scroll-element-id="'schedule-container'" :list="early.early" :item-default-height="100" uni-key="matchId" class="schedule-list p-l-20 p-r-20" :buffer-size="50">
            <template #default="slotScope">
              <ScheduleCard
                :id="'live-' + slotScope.item[slotScope.uniKey]"
                :key="'live-' + slotScope.item[slotScope.uniKey]"
                :class="{'p-t-20':slotScope.index===0}"
                :start="slotScope.start"
                :end="slotScope.end"
                :index="slotScope.index"
                :h="slotScope.height"
                :sport-id="sportId"
                :schedule="slotScope.item"
                :lottery-type="lotteryType"
              />
            </template>
</PartRenderingScroller>

如果要設計的東西,未來要套虛擬捲軸或分段捲軸時,可能要留意一下

  1. 分段捲軸 Desktop 網站架構是是 body 捲動,而 mobile 架構是 div 在捲動,可以透過傳入 scrollElementId 決定,沒傳則是 body 捲動
  2. list 外容器,不能撐padding ,要由 item 去支撐撐高,item 最外層不能用 margin,因為用程式抓寬高抓不到 margin => 之後或許可以擴充用 window.getComputedStyle 來擴充支援 margin
  3. list-item 的 css 要加 box-sizing: border-box; 不然不會把 padding 算進去
  4. 分段或虛擬捲軸, 結構要用 div ,不能用 ul li 或table 等等,因為虛擬捲軸組件會額外渲染出額外的 div
  5. 為了重算高度,list item 一定要給 id ,並用減號分隔 => “{{type}}-{{id}}”
  6. 儘量避免和其他有用到捲軸的套件整合 better scroller、vant dialog、 swiper,因為每個套件有自己的生命週期,如果一定整合進來,可能自己擴充組件功能會比較不會衝突

實作過程遇到的問題

1. 評估過 vue-virtual-scroller and vue-virtual-scroll-list 簡單功能可以套用,但遇到複雜的情境就不好套用。

原始碼也不易理解及改動,最後決定自己刻了。

2. 而在實作過程中發現,桌面版非滿版網頁,或是需要多個虛擬捲軸同時存在,則使用者體驗不是這麼好,會變成雙出現內外卷軸的情境,對於使用者來說並不是很好的體驗,

此時情境可能不適合用虛擬捲軸,而是要分段渲染卷軸。

3. 每一筆資料都不同高度,分段元件及虛擬捲軸得支援動態高度。

元件初始化時,先給預設高,並快取起來,直到渲染出來,在去更新高度,postion 的快取。

4. 虛擬捲軸在套聊天室時發現筆數一多,從最舊的資料渲染到最新時,透過自動捲動渲染,顯示時就會變得非常卡頓。

聊天室最後將渲染索引反過來渲染,最先渲染使用者看得到的,直到使用者往上捲動。

5. 先前的 Height light 資料機制,是透過操作 dom 去給 class,只要元件一重新渲染就會消失。

改用 vuex 去記錄 hight light 的 match ,依據 vuex 去判透過 vue bind 判斷需不需要 hight light。

6.同一頁有有 n 個資料,需要顯示分組相關資訊

可以將分組資訊塞到該組第一個卡片上或是採用多個分段捲軸。

7.整合 vue better scroll( 上拉整理、下拉取得資料) 、 swiper

上述都是類似虛擬捲軸機制的套件,如果要整合捲軸類型的套件,最好還是自己擴充虛擬捲軸,不然要解決兩個虛擬捲軸機制在裡面衝突。

相關程式碼

待整理


Tags

Mark Ku

Mark Ku

Software Developer

8年以上豐富網站開發經驗,直播系統、POS系統、電子商務、平台網站、SEO、金流串接、DevOps、Infra 出身,帶過幾次團隊,目前專注於北美及德國市場電商網站開發團隊。

Expertise

前端(React)
後端(C#)
網路管理
DevOps
溝通
領導

Social Media

facebook github website

Related Posts

解決前端渲染大量資料渲染效能問題 - 1
解決前端渲染大量資料渲染效能問題 - 1
September 26, 2021
1 min

Quick Links

關於我

Social Media