Element分析(組件篇)——TableBody

說明

table-body 是表格的主體部分,也是較為簡單,因此不細(xì)說。

源碼解讀

import { getCell, getColumnByCell, getRowIdentity } from './util';
import ElCheckbox from 'element-ui/packages/checkbox';

export default {
  components: {
    ElCheckbox
  },

  props: {
    store: {
      required: true
    },
    context: {},
    layout: {
      required: true
    },
    rowClassName: [String, Function],
    rowStyle: [Object, Function],
    fixed: String,
    highlight: Boolean
  },

  render(h) {
    // 計算要隱藏的列
    const columnsHidden = this.columns.map((column, index) => this.isColumnHidden(index));
    return (
      <table
        class="el-table__body"
        cellspacing="0"
        cellpadding="0"
        border="0">
        <colgroup>
          {
            this._l(this.columns, column =>
              <col
                name={ column.id }
                width={ column.realWidth || column.width }
              />)
          }
        </colgroup>
        <tbody>
          {
            this._l(this.data, (row, $index) =>
              [<tr
                style={ this.rowStyle ? this.getRowStyle(row, $index) : null }
                key={ this.table.rowKey ? this.getKeyOfRow(row, $index) : $index }
                on-dblclick={ ($event) => this.handleDoubleClick($event, row) }
                on-click={ ($event) => this.handleClick($event, row) }
                on-contextmenu={ ($event) => this.handleContextMenu($event, row) }
                on-mouseenter={ _ => this.handleMouseEnter($index) }
                on-mouseleave={ _ => this.handleMouseLeave() }
                class={ [this.getRowClass(row, $index)] }>
                {
                  this._l(this.columns, (column, cellIndex) =>
                    <td
                      class={ [column.id, column.align, column.className || '', columnsHidden[cellIndex] ? 'is-hidden' : '' ] }
                      on-mouseenter={ ($event) => this.handleCellMouseEnter($event, row) }
                      on-mouseleave={ this.handleCellMouseLeave }>
                      {
                        columnsHidden[cellIndex] ? '' : column.renderCell.call(this._renderProxy, h, { row, column, $index, store: this.store, _self: this.context || this.table.$vnode.context })
                      }
                    </td>
                  )
                }
                {
                  !this.fixed && this.layout.scrollY && this.layout.gutterWidth ? <td class="gutter" /> : ''
                }
              </tr>,
                this.store.states.expandRows.indexOf(row) > -1
                ? (<tr>
                    <td colspan={ this.columns.length } class="el-table__expanded-cell">
                      { this.table.renderExpanded ? this.table.renderExpanded(h, { row, $index, store: this.store }) : ''}
                    </td>
                  </tr>)
                : ''
              ]
            )
          }
        </tbody>
      </table>
    );
  },

  watch: {
    // 處理懸浮在某行,更改對應(yīng)的樣式
    'store.states.hoverRow'(newVal, oldVal) {
      if (!this.store.states.isComplex) return;
      const el = this.$el;
      if (!el) return;
      const rows = el.querySelectorAll('tbody > tr');
      const oldRow = rows[oldVal];
      const newRow = rows[newVal];
      if (oldRow) {
        oldRow.classList.remove('hover-row');
      }
      if (newRow) {
        newRow.classList.add('hover-row');
      }
    },
    // 處理當(dāng)前行改變
    'store.states.currentRow'(newVal, oldVal) {
      if (!this.highlight) return;
      const el = this.$el;
      if (!el) return;
      const data = this.store.states.data;
      const rows = el.querySelectorAll('tbody > tr');
      const oldRow = rows[data.indexOf(oldVal)];
      const newRow = rows[data.indexOf(newVal)];
      if (oldRow) {
        oldRow.classList.remove('current-row');
      } else if (rows) {
        [].forEach.call(rows, row => row.classList.remove('current-row'));
      }
      if (newRow) {
        newRow.classList.add('current-row');
      }
    }
  },

  computed: {
    table() {
      return this.$parent;
    },

    data() {
      return this.store.states.data;
    },

    columnsCount() {
      return this.store.states.columns.length;
    },

    leftFixedCount() {
      return this.store.states.fixedColumns.length;
    },

    rightFixedCount() {
      return this.store.states.rightFixedColumns.length;
    },

    columns() {
      return this.store.states.columns;
    }
  },

  data() {
    return {
      tooltipDisabled: true
    };
  },

  methods: {
    // 獲取行的 key,如果沒有直接返回索引
    getKeyOfRow(row, index) {
      const rowKey = this.table.rowKey;
      if (rowKey) {
        return getRowIdentity(row, rowKey);
      }
      return index;
    },

    // 判斷列是否隱藏
    isColumnHidden(index) {
      if (this.fixed === true || this.fixed === 'left') {
        return index >= this.leftFixedCount;
      } else if (this.fixed === 'right') {
        return index < this.columnsCount - this.rightFixedCount;
      } else {
        return (index < this.leftFixedCount) || (index >= this.columnsCount - this.rightFixedCount);
      }
    },

    // 獲取對應(yīng)行的樣式
    getRowStyle(row, index) {
      const rowStyle = this.rowStyle;
      if (typeof rowStyle === 'function') {
        return rowStyle.call(null, row, index);
      }
      return rowStyle;
    },

    // 獲取對應(yīng)行的類
    getRowClass(row, index) {
      const classes = [];

      const rowClassName = this.rowClassName;
      if (typeof rowClassName === 'string') {
        classes.push(rowClassName);
      } else if (typeof rowClassName === 'function') {
        classes.push(rowClassName.call(null, row, index) || '');
      }

      return classes.join(' ');
    },

    // 處理鼠標(biāo)進(jìn)入單元格
    handleCellMouseEnter(event, row) {
      const table = this.table;
      // 獲取進(jìn)入的單元格
      const cell = getCell(event);

      if (cell) {
        // 獲取對應(yīng)的列
        const column = getColumnByCell(table, cell);
        // 修改懸浮的狀態(tài)
        const hoverState = table.hoverState = {cell, column, row};
        table.$emit('cell-mouse-enter', hoverState.row, hoverState.column, hoverState.cell, event);
      }

      // 判斷是否text-overflow, 如果是就顯示tooltip
      const cellChild = event.target.querySelector('.cell');

      this.tooltipDisabled = cellChild.scrollWidth <= cellChild.offsetWidth;
    },

    // 處理鼠標(biāo)離開單元格
    handleCellMouseLeave(event) {
      const cell = getCell(event);
      if (!cell) return;

      const oldHoverState = this.table.hoverState;
      this.table.$emit('cell-mouse-leave', oldHoverState.row, oldHoverState.column, oldHoverState.cell, event);
    },

    // 處理鼠標(biāo)進(jìn)入某行
    handleMouseEnter(index) {
      // 設(shè)置該行是鼠標(biāo)懸浮的行
      this.store.commit('setHoverRow', index);
    },

    // 處理鼠標(biāo)離開某行
    handleMouseLeave() {
      this.store.commit('setHoverRow', null);
    },

    // 處理鼠標(biāo)右鍵
    handleContextMenu(event, row) {
      const table = this.table;
      table.$emit('row-contextmenu', row, event);
    },

    // 處理左鍵雙擊
    handleDoubleClick(event, row) {
      const table = this.table;
      table.$emit('row-dblclick', row, event);
    },

    // 處理左鍵單擊
    handleClick(event, row) {
      const table = this.table;
      const cell = getCell(event);
      let column;
      if (cell) {
        column = getColumnByCell(table, cell);
        if (column) {
          // 如果存在對應(yīng)的單元格,并能找到對應(yīng)的列,則觸發(fā) cell-click
          table.$emit('cell-click', row, column, cell, event);
        }
      }

      // 設(shè)置當(dāng)前行
      this.store.commit('setCurrentRow', row);

      // 觸發(fā) row-click
      table.$emit('row-click', row, event, column);
    },

    // 切換擴(kuò)展項
    handleExpandClick(row) {
      this.store.commit('toggleRowExpanded', row);
    }
  }
};

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,351評論 25 708
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 14,199評論 1 92
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,692評論 4 61
  • 強(qiáng)盜的加入讓徐偉宸的的行動小隊終于略見雛形,在徐偉宸的構(gòu)想之中,他的小隊除了他這個隊長之外,還要有一名狙擊手負(fù)責(zé)小...
    徐小賤閱讀 422評論 0 2
  • 嗯 太久沒來了 不知道 可能最近發(fā)生的太少 家人寒暄 朋友寒暄 寒暄 寒暄 只有這么多來形容 前幾天我們這 有結(jié)...
    度獨(dú)韇閱讀 244評論 0 1

友情鏈接更多精彩內(nèi)容