2021如何讓你的Table組件無限可能

在管理後臺中咱們會使用大量的表格表單組件, 導入導出各類報表, 有些場景還須要對報表數據進行可視化分析, 動態生成可視化圖表, 筆者將基於以上場景, 總結一些實用的 Table 組件開發技巧, 讓前端開發再也不吃力.javascript

往期經典

效果演示

技術點

  • 實現 Table 動態渲染
  • Table 排序, 多列排序, 自定義搜索
  • 批量導入 Excel 數據渲染 Table
  • Table 數據導出爲 Excel 文件
  • 基於 Table 數據自動生成多維度可視化報表
  • 實現簡單的 Table 編輯器

以上是幾個經常使用的業務分場景, 接下來筆者帶你們一一實現.css

技術實現

1. 實現 Table 動態渲染

通常咱們渲染表格, 大多數是預先將表格結構寫好, 比先定義好columns再向後端請求數據填充表格, 以下:前端

const columns = [
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
  },
  {
    title: '年齡',
    dataIndex: 'age',
    key: 'age',
  },
  {
    title: '住址',
    dataIndex: 'address',
    key: 'address',
  },
];
const dataSource = [
  {
    key: '1',
    name: '徐小夕',
    age: 18,
    address: '杭州夕湖區',
  }
];

<Table dataSource={dataSource} columns={columns} />
複製代碼

這種業務場景雖然能夠知足大部分後臺管理系統的Table需求, 也可使用 antd 或者 element 構建, 可是對於 lowcode 系統而言, 不少模塊都是不肯定的, 咱們須要根據協議數據來驅動 Table 的渲染.vue

好比咱們在 H5-Dooring 中配置了一個表單, 咱們要統計分析表單的數據, 因爲表單項是不肯定的, 因此咱們沒法提早定義好一個 table schema. java

那如何來動態渲染這個 Table 呢? 這裏給你們提供一個思路, 基於數據驅動 + 協議層約束. 相似於國外 SAP 的 低代碼平臺, 徹底基於 odata 協議, 咱們能夠約束表單的提交數據格式, 而後結合用戶提交的數據, 動態提取出 Table 所需的 columns, 最後再渲染 Table 組件.node

協議層主要約束不一樣字段的展現類型, 好比字符串, 按鈕, 連接, 標籤等, 用戶在提交表單以後會攜帶協議層對應的 flag 和用戶輸入的值, 這有利於咱們解析器渲染Table時能夠對不一樣的列展現不一樣的類型. 以下: react

筆者這裏簡單實現一個demo, 以下:webpack

// table數據源
let tableData = res.map((item:any,i:number) => ({ ID: nanoid(8), ...item }));
let baseRow = tableData[0],
keys = Object.keys(baseRow);
setColumns(() => {
  const baseColumn = keys.map(item => {
    return {
      title: item,
      dataIndex: item,
      key: item,
      width: item === 'ID' ? 0 : null,
      render: (v:any) => {
        if(typeof v === 'object') {
          return <> { v.map(item => <Tag color="#2F54EB">{ item.label || item }</Tag>) } </>
        }
        return item === 'ID' ? '' : v
      }
    }
  })
  baseColumn.push({
    title: '操做',
    key: 'operation',
    fixed: 'right',
    width: 100,
    render: (row) => <a onClick={() => handleDel(row)}>刪除</a>,
  })
  return baseColumn
})
複製代碼

以上咱們就實現了一個動態 Table 渲染方案, 案例中使用了 react, 你們也可使用熟悉的 vue3.0.css3

2. Table 排序, 多列排序, 自定義搜索

Table 排序, 多列排序實現方式也很簡單, 咱們只須要自定義 Table 頭部, 對排序字段提高爲 Table 的公共 State, 最後經過排序標識和排序方法進行排序便可. 目前 antd4.0已經支持多列排序, 你們能夠直接參考學習便可, 以下: 對於自定義搜索, 也就是文章開頭的 demo 展現的列搜索, 咱們能夠採用以下方案實現:git

const getColumnSearchProps = dataIndex => ({
    filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
      <div style={{ padding: 8 }}> <Input ref={node => { searchInput = node; }} placeholder={`Search ${dataIndex}`} value={selectedKeys[0]} onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])} onPressEnter={() => handleSearch(selectedKeys, confirm, dataIndex)} style={{ width: 188, marginBottom: 8, display: 'block' }} /> <Space> <Button type="primary" onClick={() => handleSearch(selectedKeys, confirm, dataIndex)} icon={<SearchOutlined />} size="small" style={{ width: 90 }} > 搜索 </Button> <Button onClick={() => handleReset(clearFilters)} size="small" style={{ width: 90 }}> 重置 </Button> </Space> </div>
    ),
    filterIcon: filtered => <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />,
    onFilter: (value, record) =>
      record[dataIndex]
        ? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase())
        : '',
    onFilterDropdownVisibleChange: visible => {
      if (visible) {
        setTimeout(() => searchInput.select(), 100);
      }
    },
    render: text =>
      searchedColumn === dataIndex ? (
        <Highlighter highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }} searchWords={[searchText]} autoEscape textToHighlight={text ? text.toString() : ''} />
      ) : (
        text
      ),
  });
複製代碼

此時咱們只須要對動態生成的columns每一列添加自定義頭部便可:

{
  title: item,
  dataIndex: item,
  key: item,
  ...getColumnSearchProps(item)
}
複製代碼

antd4.0 中也有詳細的使用方式, 這裏筆者就不一一介紹了, 效果以下: 你們也能夠在 H5-Dooring 的管理後臺中查看具體效果.

3. 批量導入 Excel 數據渲染 Table

在不少數據分析後臺中咱們須要處理不少電子表格, 用傳統的excel手動錄入的方式將慢慢被淘汰. 好比不一樣渠道方收集到了不少業務數據, 整理到 excel 中, 那如何快速保存到本身的後臺系統中呢? 通常的思路以下:

  • 經過表單的方式一條條錄入
  • 後臺解析文件處理成規範的可入庫數據結構
  • 前端實現一件導入 excel, 自動同步數據

第一種方案因爲效率過低, 適合C端用戶手動錄入, 咱們暫時忽略, 筆者將實現一下第三種方案. 實現思路以下:

這裏咱們用到了 XLSX 這個庫, 結合 FileReader API. 咱們經過FileReader 拿到excel文件的二進制數據, 而後傳給 XLSX 解析成 js object, 最後經過筆者寫的 table 渲染器生成符合規範的table數據結構. 源碼以下:

// 解析並提取excel數據
let reader = new FileReader();
reader.onload = function(e) {
  let data = e.target.result;
  let workbook = XLSX.read(data, {type: 'binary'});
  let sheetNames = workbook.SheetNames; // 工做表名稱集合
  let draftArr = {}
  sheetNames.forEach(name => {
    let worksheet = workbook.Sheets[name]; // 只能經過工做表名稱來獲取指定工做表
    for(let key in worksheet) {
      // v是讀取單元格的原始值
      if(key[0] !== '!') {
        if(draftArr[key[0]]) {
          draftArr[key[0]].push(worksheet[key].v)
        }else {
          draftArr[key[0]] = [worksheet[key].v]
        }
      }
    }
  });
  // 獲得table合法的數據產物
  const sourceData = Object.values(draftArr);
}
reader.readAsBinaryString(file);
複製代碼

拿到合法的table 數據源以後咱們就能夠進行第一節說的動態渲染 Table 的邏輯了.

經過以上的方式, 咱們能夠實現任何結構的excel表格的導入. 在導入後咱們能夠自動發送請求存儲到咱們的業務後臺中.

4. 將 Table 數據導出爲 Excel

相似的, 上面咱們介紹了將 excel 導入 table, 一樣咱們也能夠將Table 導出爲 excel, 進行數據的分發, 本地化, 好比咱們最近流行的在線文檔等應用. 筆者這裏簡單講一下實現思路:

也就是咱們第3節說的反解析. excel 文件生成筆者採用 js-export-excel 這個庫, 基於它筆者實現了一個開箱即用的方法, 避免你們燒腦造輪子. 以下:

import ExportJsonExcel from 'js-export-excel';

const generateExcel = () => {
    let option:any = {};  //option表明的就是excel文件
    let dataTable = [];  //excel文件中的數據內容
    let len = list.length;
    if (len) {
        for(let i=0; i<len; i++) {
            let row = list[i];
            let obj:any = {};
            for(let key in row) {
                if(typeof row[key] === 'object') {
                    let arr:any = row[key];
                    obj[key] = arr.map((item:any) => (typeof item === 'object' ? item.label : item)).join(',')
                }else {
                    obj[key] = row[key]
                }
            }
            dataTable.push(obj);  //設置excel中每列所獲取的數據源
        }
    }
    let tableKeys = Object.keys(dataTable[0]);
    option.fileName = tableName;  //excel文件名稱
    option.datas = [
          {
            sheetData: dataTable,  //excel文件中的數據源
            sheetName: tableName,  //excel文件中sheet頁名稱
            sheetFilter: tableKeys,  //excel文件中需顯示的列數據
            sheetHeader: tableKeys,  //excel文件中每列的表頭名稱
          }
    ]
    let toExcel = new ExportJsonExcel(option);  //生成excel文件
    toExcel.saveExcel();  //下載excel文件
}
複製代碼

5. 基於 Table 數據自動生成多維度可視化報表

在後臺管理系統和 BI 平臺中咱們會遇到不少數據分析和報表展現的需求, 接下來筆者未來介紹一下如何基於 Table 數據動態生成多維度可視化分析報表.

筆者在以前的文章中介紹過 度量行這個概念, 對於數據分析而言, 咱們也要考慮可分析維度的概念, 好比什麼是可分析的, 什麼是不可分析的. 好比咱們又一個表格, 裏面有以下結構: 對於聯繫方式而言, 它是不可度量的, 即分析該項指沒有任何價值, 因此在自動生成多維度分析中咱們理論上不因該分析它, 基於這個原理, 咱們來設計一個簡單的自動生成多維度可視化報表的方案.

5.1 基於數據源獲取維度數據

咱們針對具備範圍屬性的維度進行度量, 生成度量數據, 代碼以下:

const generateDistData = (key:string, list:any) => {
    let distDataMap:any = {},
        distData = []
    list.forEach((item:any) => {
        // 當前緯度的類別
        let curKey = typeof item[key] === 'object' ? item[key][0].label : item[key];
        if(distDataMap[curKey]) {
            distDataMap[curKey]++;
        }else {
            distDataMap[curKey] = 1;
        }
    })

    // 生成目標數組
    for(let key in distDataMap) {
        distData.push({name: key, value: distDataMap[key]})
    }
    return distData
  }
複製代碼

此時咱們只須要根據維度的字段, 便可獲取某一維度的數據值, 後經過可視化組件渲染便可.

5.2 基於某一維度生成可視化報表

咱們用@ant-design/charts, 代碼以下:

<div className={styles.anazlyHeader}>
    <div className={styles.anazlyItem}> <span>分析緯度: </span> <Select style={{ width: 120 }} onChange={(v) => handleAnazlyChange(0, v)} defaultValue={keys[0]}> { keys.map((item,i) => { return <Option value={item} key={i}>{ item }</Option> }) } </Select> </div>
</div>
<div className={styles.anazlyContent}> { !!config && <Pie {...config} /> } </div>
複製代碼

實現效果以下:

6. 實現簡單的 Table 編輯器

實現 Table 編輯器其實筆者在 前端如何一鍵生成多維度數據可視化分析報表 已經詳細分析過了,也集成在了H5-Dooring 的可視化組件編輯器中, 具體 demo 以下:

你們感興趣能夠研究一下.

最後

目前筆者也在持續更新H5編輯器 H5-Dooring, 最近來同步一下功能:

  • 修復圖片庫選擇bug
  • 添加省市級聯組件
  • 添加批量導入 excel 數據的能力
  • 添加表單自定義校驗
  • 音頻組件添加自動播放控制, 循環播放等配置項
  • 添加橫向滑動組件

以爲有用 ?喜歡就收藏,順便點個吧,你的支持是我最大的鼓勵!微信搜 「趣談前端」,發現更多有趣的H5遊戲, webpack,node,gulp,css3,javascript,nodeJS,canvas數據可視化等前端知識和實戰.

相關文章
相關標籤/搜索