ant-design-vue中table自定義列

1. 使用背景

在項目中使用ant-vuea-table控件過程當中,須要顯示序號列或者在列中顯示圖片,超鏈,按鈕等UI信息。通過查詢文檔customCellcustomRender能夠實現以上需求,好比實現以下表格數據渲染javascript

2. slots&scopedSlots做用

在查看文檔過程當中,在類型一欄中常常看到 xxx|slot |slot-scope 這樣的描述信息。好比customRender在文檔中的描述信息html

屬性 說明 類型
customRender 生成複雜數據的渲染函數.. Function(text, record, index){}|slot-scope

在最初一直覺得在列中能夠是以下配置的vue

// 公衆號:小院不小 date 20210205 wx:464884492
const tableColumn = [
      {
        title: '遊戲名稱',
        dataIndex: 'title',
        customRender:'xxslot'
      }
]
複製代碼

這樣定義後執行npm run serve在瀏覽器會出現customRender is not function 的錯誤信息。以及後來看到有以下寫法java

// 公衆號:小院不小 date 20210205 wx:464884492
const tableColumn = [
      {
        title: '遊戲名稱',
        dataIndex: 'title',
        scopedSlots: {
          customRender: "customRender"
        }
      }
]
複製代碼

還有很長一段時間不明白scopedSlots這個對象的屬性爲啥是customRender, 還有其餘的什麼屬性嗎?當時知識還不完善沒有理解到文檔上使用 columns 時,能夠經過該屬性配置支持 slot-scope 的屬性的含義node

雖然知道怎麼用了,但仍是有必要了解下它是如何運行的。咱們知道在vue中能夠經過this.$slotsthis.$scopedSlots分別訪問靜態插槽和做用域插槽。在文件components\table\index.jsx中能夠找到組件庫對scopedSlotsslots轉換成具體函數的過程,代碼以下面試

// 公衆號:小院不小 date 20210205 wx:464884492
 ...
 // 獲取插槽
 const { $slots, $scopedSlots } = this;
 // 轉換靜態插槽
 Object.keys(slots).forEach(key => {
      const name = slots[key];
      if (column[key] === undefined && $slots[name]) {
        column[key] = $slots[name].length === 1 ? $slots[name][0] : $slots[name];
      }
    });
 // 轉換動態插槽 
 Object.keys(scopedSlots).forEach(key => {
  const name = scopedSlots[key];
  if (column[key] === undefined && $scopedSlots[name]) {
    column[key] = $scopedSlots[name];
  }
 });
複製代碼

從以上代碼也能夠知道,若是您定義以下的列配置,自定插槽會失效,如下代碼該列會所有顯示123npm

// 公衆號:小院不小 date 20210205 wx:464884492
{
    title: "customRender|slot-scope",
    dataIndex: '',
    customRender: () => 123,
    scopedSlots: {
      customRender: "customRender"
    }
}
複製代碼

也就是說customRender定義成函數的優先級高於做用域插槽瀏覽器

3. customCell

customCell影響的是vnode中的屬性信息,你能夠改變當前列的樣式等相關信息,在文件 components\vc-table\src\TableCell.jsx 對應代碼片斷markdown

// 公衆號:小院不小 date 20210205 wx:464884492
...
 if (column.customCell) {
  tdProps = mergeProps(tdProps, column.customCell(record, index));
}
...
 return (
  <BodyCell class={cellClassName} {...tdProps}> {indentText} {expandIcon} {text} </BodyCell>
);    
複製代碼

因此這個對象能夠傳遞值能夠參考vue官方文檔深刻數據對象中的描述。你能夠返回以下對改變當前列的字體大小和顏色dom

// 公衆號:小院不小 date 20210205 wx:464884492
 return {
    style: {
      color: 'red',
      fontSize: '14px'
    }
 }
複製代碼

也可經過以下改變顯示的內容

// 公衆號:小院不小 date 20210205 wx:464884492
return {
  domProps: {
      innerHTML: record.title + "#" + (index + 1)
    }
}
複製代碼

4. customRender

customRender也能夠影響當前列的顯示信息,不過它更靈活。能夠返回一段jsx獲取返回一個相似customCell同樣的屬性信息。不過從代碼來看,它只接收一下屬性attrspropsclassstylechildren,並且它的優先級也沒有customCell優先級高。customRender能夠是一個插槽,也能夠是一個函數。 看成爲插槽使用時代碼應該以下所示

// 公衆號:小院不小 date 20210205 wx:464884492
[{
  title: "customRender|slot-scope",
  dataIndex: '',
  scopedSlots: {
    customRender: "customRender"
  }
},{
  title: "customRender|slot-scope",
  dataIndex: '',
  slots: {
    customRender: "customRender"
  }
}]
複製代碼

從上邊瞭解到的插槽知識能夠知道做用域插槽的優先級高於靜態插槽也就是說,在一個列中分別配置了鍵值相等的靜態插槽和做用域插槽,將優先顯示做用域插槽的內容 看成爲函數使用時,代碼應該以下所示

// 公衆號:小院不小 date 20210205 wx:464884492
[{
  title: '遊戲特色',
  dataIndex: 'desc',
  customRender: (text, record, index) => {
    if (index == 1) {
      return <div> {text} <span style="color:blue"> @小院不小</span></div>
    }
    return {
      attrs:{},
      props:{},
      class:{},
      style:{},
      children: text
    }
  }
}]
複製代碼

兩種返回值組件經過isInvalidRenderCellText函數判斷。判斷是不是jsx的方式主要代碼以下

// 公衆號:小院不小 date 20210205 wx:464884492
function isValidElement(element) {
  return (
    element &&
    typeof element === 'object' &&
    'componentOptions' in element &&
    'context' in element &&
    element.tag !== undefined
  ); 
}
複製代碼

經過上邊的說明,咱們就能很好的使用customRender屬性了。不過咱們仍是有必要了解一下,這段屬性對應源代碼邏輯。在文件components\vc-table\src\TableCell.jsx 對應的代碼片斷以下

// 公衆號:小院不小 date 20210205 wx:464884492
if (customRender) {
  text = customRender(text, record, index, column);
  if (isInvalidRenderCellText(text)) {
    tdProps.attrs = text.attrs || {};
    tdProps.props = text.props || {};
    tdProps.class = text.class;
    tdProps.style = text.style;
    colSpan = tdProps.attrs.colSpan;
    rowSpan = tdProps.attrs.rowSpan;
    text = text.children;
  }
}

if (column.customCell) {
  tdProps = mergeProps(tdProps, column.customCell(record, index));
}
複製代碼

5. 總結

ant的組件很靈活,不少須要經過擴展來實現一些特殊的功能.customRendercustomCell均可以實現自定義列信息。在什麼場景下使用,還須要根據不一樣業務訴求。好比我要改變列字體,顏色等,咱們就優先考慮customCell.根據上面的介紹這裏有一個面試題代碼以下

// 公衆號:小院不小 date 20210205 wx:464884492
{
  title: "自定義列",
  dataIndex: '',
  customRender:()=>'函數渲染'
   scopedSlots: {
    customRender: "scopedSlots"
  },
  slots: {
    customRender: "slots"
  }
}
複製代碼

請問列自定義列最終渲染的內容是

  • A 函數渲染
  • B scopedSlots
  • C slots

若是想知道答案或須要Demo源碼請掃描下方的二維碼,關注公衆號[小院不小],回覆ant-table獲取.

相關文章
相關標籤/搜索