美文网首页
基于element-ui的el-table进行二次封装——通过配

基于element-ui的el-table进行二次封装——通过配

作者: videring | 来源:发表于2020-08-11 10:20 被阅读0次

    麻烦点

    • 在使用element-ui的el-table组件时,需要手工写入大量el-table-column,费时费力;在需要用到Scoped slot时,需要创建el-table-column,并在其中加入template标签(用法:<template slot-scope="props">/*...*/</template>)。
    • 不支持可配置

    改善点

    • 全部配置化,自动生成el-table-column,其中columns对应El-Table-column Attributes,props对应El-Table Attributes,El-Table原有事件照原先用法使用即可
    • 通过render进行了封装,首先el-table原有功能全部支持且用法不变
    • 至于Scoped slot用法,则加入renderCell配置项进行支持
    • 支持多级表头

    用法示例

    // test
    <template>
      <div class="test">
          <config-table
                  :columns="tableColumns"
                  :loading="loading"
                  :props="tableProps"
                  @cell-click="handleCellClick"
                  @row-click="handleCellClick"
                  ref="cRef"
          >
              <div slot="append">测试slot append</div>
          </config-table>
          <el-button @click="toggle">更改选中状态</el-button>
      </div>
    </template>
    
    <script>
    import configTable from './index'
    
    export default {
      name: 'test',
      components: {
        configTable
      },
      data() {
        return {
          loading: false,
          tableProps: {
            'show-summary': true,
            'highlight-current-row': true,
            data: [
              {
                a: '123',
                b: '哈喽',
                c: '高层',
                d: 'm²',
                e: 234,
                f: 11.1,
                g: 12345
              },
              // {
              //   a: 'tyhj',
              //   b: '中国',
              //   c: '中层',
              //   d: 'kilo',
              //   e: 1111,
              //   f: 33.3,
              //   g: 456
              // }
            ]
          },
          tableColumns: [
            {
              type: 'selection',
              width: 100
            },
            {
              label: '项目编码',
              prop: 'a',
            }, {
              label: '项目名称',
              prop: 'b',
            }, {
              label: '项目特征',
              prop: 'c',
            }, {
              label: '单位',
              prop: 'd',
              minWidth: '200px',
              formatter: (row, column) => `单位:${row[column.property]}`,
              renderHeader: (h, d) => `我是${d.column.label}`, // 对应El-Table-column Attributes render-header
              // 优先级高于formatter,相当于el-table-column中作用域插槽
              renderCell: (h, props) => h('span', `${props.column.label}ing:${props.row[props.column.property]}`) // 这是自定义的El-Table-column Attributes,对应scopedSlot!!!
            }, {
              label: '基准模型',
              prop: '',
              render: null,
              data: null,
              children: [
                {
                  label: '工程量',
                  prop: 'e',
                }, {
                  label: '综合单价',
                  prop: 'f',
                }, {
                  label: '综合合价',
                  prop: 'g',
                }
              ]
            }
          ],
        }
      },
      methods: {
        handleCellClick(...args) {
          console.log(args)
        },
        toggle() {
          this.$refs.cRef.$refs.ref.toggleRowSelection(this.tableProps.data[0])
        },
      }
    }
    </script>
    
    <style lang="scss" scoped>
      .test {
      }
    </style>
    

    效果图

    源码

    <script>
    export default {
      name: 'config-table',
      props: {
        loading: {
          type: Boolean,
          default: () => false
        },
        props: { // 对应El-Table Attributes
          required: true,
          type: Object
        },
        columns: { // 对应El-Table-column Attributes
          required: true,
          type: Array,
          default: () => []
        },
      },
      render(createElement) {
        const render = (h, data) => {
          data = Array.isArray(data) ? data : [data]
          return data.map(col => {
            const { children } = col
            const props = {
              ...col
            }
            const hasChildren = Array.isArray(children) && children.length
            const hasCellRender = typeof col.renderCell === 'function'
            let cS = []
            if (hasChildren) {
              cS = render(h, children)
            }
            const colProps = {
              props
            }
            if (hasCellRender) {
              colProps.scopedSlots = {
                default(ps) {
                  return col.renderCell(h, ps) // 通过renderCell,支持scopedSlots
                }
              }
            }
            return h('el-table-column', colProps, hasChildren ? cS : []) // 通过children属性,支持多级表头
          })
        }
        return createElement('el-table', {
          class: 'config-table',
          props: {
            ...this.props
          },
          on: {
            ...this.$listeners // 支持El-Table 原有所有Events
          },
          directives: [
            {
              name: 'loading',
              value: this.loading // 支持loading
            }
          ],
          ref: 'ref', // 通过这个ref,对应El-Table Methods
        }, render(createElement, this.columns).concat(createElement('template', { slot: 'append' },this.$slots.append))) // 支持El-Table slot append
      }
    }
    </script>
    
    <style lang="scss" scoped>
      .config-table {
      }
    </style>
    
    

    相关文章

      网友评论

          本文标题:基于element-ui的el-table进行二次封装——通过配

          本文链接:https://www.haomeiwen.com/subject/pceedktx.html