基于 antd 风格的 element-table + pagination 的二次封装

前言

本次封装基于 antd 风格, 实现高度可配置的表格封装配置。原本想经过 vue.extends 去封装的,奈何几个月没写过 vue ,并且对 vueextends 不熟悉因此放弃了...javascript

以前有小伙伴确实引用了个人代码,发现封装出现了一些纰漏,对此十分抱歉,以前封装的太仓促了。几个月前的代码,如今从新封装又有了新的体会。css

更新时间 【2018.11.09】,效果以下:html

API 说明

  • columns : 必选, 列描述数据对象, Array
  • dataSource : 必选, 数据数组
  • options : 必选, 表格参数控制, maxHeight、stripe 等等..
  • fetch : 获取数据的 Function
  • pagination : 分页信息,不传则不显示分页
  • row-click :当某一行被点击时会触发该事件
  • selection-change : 当选择项发生变化时会触发该事件
  • 其余的 api 能够自行添加

其余说明我在代码注释中写的很清楚了,请自行查看。vue

根据条件渲染: 只经过 render 去判断参数不一样而渲染不同的表格数据。 render 函数能够渲染任何你想要的组件java

值得注意的是,this 对象的绑定不要出错了,若是须要更多加强的功能,各位能够自行添加...react

Home.vue 组件

<template>
    <div>
      <h2>Home</h2>
      <CommonTable :columns="columns" :dataSource="tableData" :options="options" :fetch="fetchTableData" :pagination="pagination" @row-click="handleRowClick" @selection-change="handleSelectionChange" />
    </div>
</template>

<script> import axios from 'axios' import CommonTable from '../components/Table' export default{ components:{ CommonTable }, data(){ return { columns: [ { prop: 'id', label: '编号', width: 60 }, { prop: 'title', label: '标题', // render 能够根据你想要渲染的方式渲染 // jsx 不提供 v-model 指令,若你想要使用,,推荐使用插件 babel-plugin-jsx-v-model // jsx https://github.com/vuejs/babel-plugin-transform-vue-jsx render: (row, index) => { return ( <span style="color: blue" onClick={e => this.handleClick(e, row)}>{row.title}</span> ) } }, { prop: 'author', label: '做者' }, { button: true, label: '按钮组', group: [{ // you can props => type size icon disabled plain name: '编辑', type: 'warning', icon: 'el-icon-edit', plain: true, onClick: (row, index) => { // 箭头函数写法的 this 表明 Vue 实例  console.log(row, index) } }, { name: '删除', type: 'danger', icon: 'el-icon-delete', disabled: false, onClick(row) { // 这种写法的 this 表明 group 里的对象 this.disabled = true console.log(this) } }] } ], tableData: [ { id: 1, title: '标题1', author: '郭大大' }, { id: 2, title: '标题2', author: '郭大大2' } ], pagination: { total: 0, pageIndex: 1, pageSize: 15 }, options: { mutiSelect: true, index: true, // 显示序号, 多选则 mutiSelect loading: false, // 表格动画 initTable: true, // 是否一挂载就加载数据 } } }, methods: { handleClick(e, row){ //transform-vue-jsx 的nativeOnClick 失效 , 因此采用 event.cancelBubble 控制点击事件的冒泡... 若是点击事件不影响你的点击行事件,能够不传 e.cancelBubble = true // 中止冒泡,不然会触发 row-click console.log(row) }, fetchTableData() { this.options.loading = true axios.post('https://www.easy-mock.com/mock/5b3f80edfa972016b39fefbf/example/tableData', { pageIndex: this.pagination.pageIndex, pageSize: this.pagination.pageSize }).then(res => { const { list, total } = res.data.data this.tableData = list this.pagination.total = total this.options.loading = false }).catch((error) => { console.log(error) this.options.loading = false }) }, handleRowClick(row, event, column){ // 点击行的事件,同理能够绑定其余事件 console.log('click row:',row, event, column) }, handleSelectionChange(selection){ console.log(selection) } } } </script>
复制代码

Table.vue 组件

<template>
  <div>
    <el-table v-loading="options.loading" :data="dataSource" :max-height="options.maxHeight" :stripe="options.stripe" :border="options.border" @row-click="handleRowClick" @selection-change="handleSelectionChange" header-row-class-name="table-header-row">

      <!--selection选择框-->
      <el-table-column v-if="options.mutiSelect" type="selection" style="width:50px" align="center"></el-table-column>

      <!--序号-->
      <el-table-column v-if="options.index" label="序号" type="index" width="50" align="center"></el-table-column>

      <!--数据列-->
      <template v-for="(column, index) in columns">
        <el-table-column :key="index" :prop="column.prop" :label="column.label" :align="column.align||'center'" :width="column.width" :fixed="column.fixed">
          <template slot-scope="scope">

            <template v-if="!column.render">
              {{scope.row[column.prop]}}
            </template>

             <!-- render -->
            <template v-else>
              <RenderDom :row="scope.row" :index="index" :render="column.render" />
            </template>

            <!-- render button -->
            <template v-if="column.button">
              <template v-for="(btn, i) in column.group">
                <el-button :key="i" :type="btn.type" :size="btn.size || 'mini'" :icon="btn.icon" :disabled="btn.disabled" :plain="btn.plain" @click.stop="btn.onClick(scope.row, scope.$index)" >{{btn.name}}</el-button>
              </template>
            </template>

            <!-- slot 你能够其余经常使用项 -->

          </template>

        </el-table-column>
      </template>

    </el-table>

     <!-- 分页 -->
    <el-pagination v-if="pagination" :total="pagination.total" :page-sizes="[20, 50, 100, 500, 5000]" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleIndexChange" style="margin-top: 20px;text-align: right" ></el-pagination>

  </div>
</template>

<script> export default { components: { RenderDom: { functional: true, // 函数式组件 - 无 data 和 this 上下文 => better render props: { row: Object, index: Number, render: Function }, /** * @param {Function} createElement - 原生建立dom元素的方法, 弃用,推荐使用 jsx * @param {Object} ctx - 渲染的节点的this对象 * @argument 传递参数 row index */ render(createElement, ctx){ const { row, index } = ctx.props return ctx.props.render(row, index) } } }, props:{ dataSource: Array, options: Object, // 表格参数控制 maxHeight、stripe 等等... columns: Array, fetch: Function, // 获取数据的函数 pagination: Object // 分页,不传则不显示 }, created() { // 传入的options覆盖默认设置 this.$parent.options = Object.assign({ maxHeight: 500, stripe: true, // 是否为斑马纹 border: true }, this.options) this.options.initTable && this.fetch() }, methods: { handleSizeChange(size) { // 切换每页显示的数量 this.pagination.pageSize = size this.fetch() }, handleIndexChange(current) { // 切换页码 this.pagination.pageIndex = current this.fetch() }, handleSelectionChange(selection) { this.$emit('selection-change', selection) }, handleRowClick(row, event, column) { this.$emit('row-click', row, event, column) } } } </script>

<style> .el-table th, .el-table tr.table-header-row { background: #e5c5d2; /* 示例, 对表格样式上的修饰 */ } </style>
复制代码

结语

上述代码封装完整性可能不是这么高,但思路在呢,若是须要更多配置,各位能够在进行增强...ios

吐槽一下,原本是想 props 数据来重写 table 参数,相似 react:git

<Home>
  <ComonTable {...props} > </Home>

// ComonTable
<el-table {...props.options}>
</el-table> 复制代码

因此想到继承,本身又不熟悉。 并且发现 vue 展开绑定多个属性是不能够的: 多是我没 google 到。若是能够,请大佬告知一声,谢谢github

相关文章
相关标签/搜索