開源 UI 庫中,唯一同時實現了大表格虛擬化和樹表格的 Table 元件

漆工發表於2019-01-18

背景

有這樣一個需求,一位 React Suite(以下簡稱 rsuite)的使用者,他需要一個 Table 元件能夠像 Jira Portfolio 一樣,支援樹形資料,同時需要支援大資料渲染。 截止到目前(2019年1月17日)為止,開源 UI 庫中沒有找到可以支援的元件,所以 rsuite 在最新的版本中支援這一特性。

接下來,我們看一下 rsuite 中是怎麼支援這兩個功能?

大表格虛擬化

首先,我們看一下支援大資料渲染,在頁面中渲染過多的 DOM 元素會帶來效能問題,必須得有一種解決方案去優化它,我們暫且叫做大表格虛擬化。

所謂的大表格虛擬化,其實就是為表格設定一個較大的資料(比如 10000 條資料),然後虛擬一個表格隱藏掉不需要顯示的資料。

為了解決讓瀏覽器渲染的大量 DOM 時候出現的效能問題,我們不能把 10000 條資料都渲染到頁面,採用一種方式,只渲染可視範圍內資料。 同時為表格設定一個滾動條,只有在滾動到需要顯示的區域時候才渲染該區域的資料,減少的 DOM 數量。

開源 UI 庫中,唯一同時實現了大表格虛擬化和樹表格的 Table 元件

預覽地址

以上這是一個 10000 條資料的 Table,渲染後的 HTML 結構是:

開源 UI 庫中,唯一同時實現了大表格虛擬化和樹表格的 Table 元件

我們可以看到在 Table 中只渲染了 14 個 rs-table-row ,其中第一個和最後一個是沒有 children, 只是一個擁有高度的佔位符。 每一個 rs-table-row 都是絕對定位,所以即使 Table 中刪除一個 Row, 或者新增一個 Row ,也不會改變其他 Row 的位置。 在這樣的基礎上,通過獲取滾動條的滾動的位置,就很容易判斷當前 Row 的 top 值是否在 Table 的可視範圍內,同時更新所有的 Row。

很多優秀的庫都實現了這樣的功能,原理基本一致,比如 react-virtualized 就提供 Table 元件,但是他不支援 Tree。

樹形表格

在表格中展示樹形資料的需求,我們見得比較多就像甘特圖表格展示那樣。它有子父層級關係,可以展開子節點。

開源 UI 庫中,唯一同時實現了大表格虛擬化和樹表格的 Table 元件

這樣一個表格,很多 Table 元件都支援,但是如果同時需要支援虛擬化就相對比較麻煩,因為在展開關閉節點的時候需要重新計算顯示的 DOM 以及設定滾動條的位置。

開源 UI 庫中,唯一同時實現了大表格虛擬化和樹表格的 Table 元件

rsuite Table 元件之前的版本中,渲染的樹形表格的 DOM 結構是一棵 Tree。 所以首先需要把 Tree 拍平,轉換一個一維陣列,為每一個節點設定父節點,通過父節點的深度渲染 Tree 節點的相對位置。 然後就比較好處理,只需要在點選展開關閉節點按鈕的時候,處理好資料的過濾。

安裝與使用

rsuite 的 Table 元件的設計,對開發還是非常方便,通過 <Table><Column><Cell><HeaderCell> 元件定義結構,通過賦值data 屬性渲染表格資料。

安裝

npm install rsuite --save
複製程式碼

如果你在專案只希望用到 Table, 不想安裝整個 rsuite 庫,你可以單獨安裝 rsuite-table

示例程式碼:

import { Table } from 'rsuite';

const { Column, HeaderCell, Cell } = Table;
const data = [{ id: 1, name: 'foobar', email: 'foobar@xxx.com' }];

ReactDOM.render(
  <Table height={400} data={data}>
    <Column width={70} align="center" fixed>
      <HeaderCell>編號</HeaderCell>
      <Cell dataKey="id" />
    </Column>
    <Column width={200} fixed>
      <HeaderCell>姓名</HeaderCell>
      <Cell dataKey="name" />
    </Column>
    <Column width={200}>
      <HeaderCell>郵箱</HeaderCell>
      <Cell dataKey="email" />
    </Column>
  </Table>
);
複製程式碼

最後

最後,對於一個成熟的 Table 元件怎麼能只有這點功能,所以它還支援:

  • 自定義調整列寬
  • 鎖定列
  • 自動換行
  • 排序
  • 分頁
  • 編輯
  • 合併單元格
  • 自定義單元格
  • 自動列寬
  • 可展開行

剩下唯一的問題,就是您是否在專案中嘗試它。

相關文章