1. 程式人生 > >Web長列表的救星?谷歌推出Virtual Scroller[轉]

Web長列表的救星?谷歌推出Virtual Scroller[轉]

原文連結:mp.weixin.qq.com

  譯者|無明編輯|覃雲在剛剛結束的 Chrome dev summit 2018 上,谷歌工程經理 Gray Norton 向我們介紹 virtual-scroller,一個 Web 滾動元件,未來它可能會成為 Web 高層級 API(Layered API)的一部分。它的目標是解決長列表的效能問題,消除離屏渲染。該專案處於研發中,你可以在 GitHub 檢視它的開發者預覽版本。

  眾所周知,渲染效能主要取決於渲染量, 過多的 DOM 會使你的網站速度變得很慢,即使在本地,也會出現相同的問題,但若通過虛擬滾動的方式,也就是在使用者滾動時用足夠的內容填充螢幕並不斷更新,就能讓網站保持高速執行,這也是 virtual-scroller 的基本原理。

詳解 virtual-scroller 

  <virtual-scroller>是未來 Web 平臺的一個潛在特性,是 layered API 專案的一部分,用於將 JavaScript 物件集對映到 DOM 節點上,並且只渲染當前可見的 DOM 節點,其餘部分為“虛擬”的。

  示例

<script type="module"
        src="std:virtual-scroller|https://some.cdn.com/virtual-scroller.js">
</script>

<virtual-scroller></virtual-scroller>

<script type="module">
  const scroller = document.querySelector('virtual-scroller');
  const myItems = new Array(200).fill('item');

  scroller.updateElement = (child, item, index) => {
    child.textContent = index + ' - ' + item;
    child.onclick = () => console.log(`clicked item #${index}`);
  };

  // This will automatically cause a render of the visible children
  // (i.e., those that fit on the screen).
  scroller.itemSource = myItems;
</script>

  預設情況下,這個示例中建立的虛擬滾動條內的元素為<div>,並將會被回收。更多示例請參閱:

  https://github.com/valdrinkoshi/virtual-scroller/blob/master/demo/index.html

 virtual-scroller demo

   

API 介紹 

createElement 屬性

型別:function(item: any, itemIndex: number) => Element

  在設定這個屬性時,使用工廠函式來配置虛擬滾動條,這個工廠函式會在指定索引位置的專案首次準備好在 DOM 中顯示時建立一個元素。

  在首次呼叫時,createElement 將搜尋第一個<template>元素,該元素本身在其模板內容中至少也包含了一個子元素。如果存在,它將通過克隆該子元素來建立新元素。否則,它將建立一個<div>元素。對於這兩種情況,如果 recycleElement 為預設值,它將回收 DOM 節點。

如果 recycleElement 為預設值,那麼更改這個屬性的預設值將自動將 recycleElement 重置為 null。

 updateElement 屬性

型別:function(child: Element, item: any, itemIndex: number)

  在設定這個屬性時,使用一個函式來配置虛擬滾動條,這個函式將使用指定索引處的專案的資料來更新元素。

 這個屬性將在以下場景中被呼叫:

  • 使用者滾動滾動條,更改專案元素的可見性。在這種情況下,將為所有新的可見元素呼叫 updateElement。

  • 開發人員修改了 itemSource 屬性。

  • 開發人員呼叫了 itemsChanged(),它將為所有當前可見的元素呼叫 updateElement。

  預設的 updateElement 將子元素的 textContent 設定為給定項。幾乎所有使用的地方都需要改變這個行為。

 recycleElement 屬性

  型別:function(child: Element, item: any, itemIndex: number)

  如果專案的元素不再可見,recycleElement 預設會將它回收,並將其與 DOM 連線,預設的 createElement 就可以重用它。

  當專案元素不再可見時,將這個屬性設定為 null 可以將它從 DOM 中刪除,並防止被預設的 createElement 回收。

  通常,這個屬性會被自定義,以便引入自定義的節點回收邏輯。

 itemSource 屬性

型別:Array 或 ItemSource

  設定這個屬性可以控制滾動條如何將可見索引對映到對應項。然後,這些項被提供給各種自定義渲染函式:createElement、updateElement、recycleElement。

如果提供的是陣列,它將被轉換為 ItemSource 例項,這個例項將返回陣列中的元素,就像在呼叫 ItemSource.fromArray(array) 一樣(沒有 key 引數)。

 layout 屬性

型別:string

值可以為:

  • “vertical”(預設);

  • “horizontal”;

  • “vertical-grid”;

  • “horizontal-grid”。

也可以設定為元素的屬性,例如<virtual-scroller layout=“horizontal-grid"></virtual-scroller>

 itemsChanged() 方法

這將重新渲染所有當前顯示的元素,使用 updateElement 來更新它們。

通常需要在要顯示的資料發生變化時呼叫它,包括對資料的新增、刪除和修改。

 scrollToIndex 方法

要滾動到指定的索引,可選擇使用以下位置之一:

  • “start”:將專案的開頭與滾動條可見部分的開頭對齊;

  • “center”:將專案的中心與滾動條可見部分的中心對齊;

  • “end”:將專案的末尾與滾動條可見部分的末尾對齊;

  • “nearest”:如果專案位於滾動條可見部分的中心之前,那麼與“start”一樣;如果它位於滾動條可見部分的中心之後,則與“end”一樣。

 “rangechange”事件

Bubbles: false / Cancelable: false / Composed: false

當滾動條完成渲染新的專案範圍時觸發,例如,使用者滾動了滾動條。這個事件是 RangeChangeEvent 的一個例項,它具有以下屬性:

  • first:一個數字,給出當前渲染的第一個專案的索引。

  • last:一個數字,給出當前渲染的最後一個專案的索引。

 ItemSource 類

ItemSource 類代表了一種將索引轉換為 JavaScript 值的方法。你可以像這樣建立它們:

const source = new ItemSource({
  item(index) { ... },
  getLength() { ... },
  key(index) { ... }
});

  例如,要建立一個從 contacts 陣列中獲取專案的 ItemSource,並使用 contact.id 作為鍵,你可以這樣:

const contactsSource = new ItemSource({
  item(index) { return contacts[index]; },
  getLength() { return contacts.length; },
  key(index) { return contacts[index].id; }
});

 還有一個工廠方法 ItemSource.fromArray(array [,key]) 可以更容易地完成這個操作:

const contactsSource = ItemSource.fromArray(contacts, c => c.id);

  將一個專案傳給 fromArray() 的引數 key,並且返回該物件的唯一鍵。如果沒有指定引數 key,則將專案索引作為鍵。

  ItemSource 類的主要用途是賦值給<virtual-scroller>元素的 itemSource 屬性,所以目前它唯一的公共 API 中只有一個 length 屬性。

  參考連結:https://github.com/valdrinkoshi/virtual-scroller