element vue 通用表格组件封装

一.、新建一个表格的Component

在这里插入图片描述
1.table.vue内容如下

<template>
  <div class="lb-table">
    <el-table
      ref="elTable"
      v-bind="$attrs"
      :stripe="stripe"
      :border="border"
      :data="data"
      row-key="id"
      :tree-props="{children: '_child', hasChildren: 'hasChildren'}"
      size="medium"
      v-on="$listeners"
    >
      <template v-for="item in column">
        <template>
          <!-- 操作列表 -->
          <el-table-column
            v-if="item.prop == 'action'"
            :key="item.prop"
            v-bind="$attrs"
            :prop="item.prop"
            :label="item.label"
            :fixed="item.fixed"
            :type="item.type"
            :index="item.index"
            :column-key="item.columnKey"
            :width="item.width"
            :min-width="item.minWidth"
            :sortable="item.sortable || false"
            :sort-method="item.sortMethod"
            :sort-by="item.sortBy"
            :sort-orders="item.sortOrders"
            :resizable="item.resizable || true"
            :formatter="item.formatter"
            :show-overflow-tooltip="item.showOverflowTooltip || true"
            :align="item.align || 'center'"
            :header-align="item.headerAlign || item.align || 'center'"
            :class-name="item.className"
            :label-class-name="item.labelClassName"
            :selectable="item.selectable"
            :reserve-selection="item.reserveSelection || false"
            :filters="item.filters"
            :filter-placement="item.filterPlacement"
            :filter-multiple="item.filterMultiple"
            :filter-method="item.filterMethod"
            :filtered-value="item.filteredValue"
          >
            <template slot-scope="scope">
              <el-button
                v-for="(act, actionIndex) in item.children"
                :key="actionIndex"
                type="text"
                :class="{danger: act['event'] === 'handleDelete'}"
                @click="handleAction(act,scope.row)"
              >{{ act.name }}</el-button>
            </template>
          </el-table-column>
          <!-- 普通列表 -->
          <el-table-column
            v-else
            :key="item.prop"
            v-bind="$attrs"
            :prop="item.prop"
            :label="item.label"
            :type="item.type"
            :index="item.index"
            :column-key="item.columnKey"
            :width="item.width"
            :min-width="item.minWidth"
            :sortable="item.sortable || false"
            :sort-method="item.sortMethod"
            :sort-by="item.sortBy"
            :sort-orders="item.sortOrders"
            :resizable="item.resizable || true"
            :formatter="item.formatter"
            :show-overflow-tooltip="item.showOverflowTooltip || true"
            :align="item.align || 'center'"
            :header-align="item.headerAlign || item.align || 'center'"
            :class-name="item.className"
            :label-class-name="item.labelClassName"
            :selectable="item.selectable"
            :reserve-selection="item.reserveSelection || false"
            :filters="item.filters"
            :filter-placement="item.filterPlacement"
            :filter-multiple="item.filterMultiple"
            :filter-method="item.filterMethod"
            :filtered-value="item.filteredValue"
          >
            <template slot-scope="scope">
              <slot
                :scope="handleScope(scope)"
                :name="item.prop"
              >
                {{ scope.row[item.prop] }}
              </slot>
            </template>
          </el-table-column>
        </template>
      </template>
    </el-table>
    <el-pagination
      v-if="pagination"
      class="table-pagination"
      v-bind="$attrs"
      v-on="$listeners"
      @current-change="currentChange"
      @size-change="sizeChange"
    />
  </div>
</template>

<script>
export default {
  props: {
    column: Array,
    data: Array,
    pagination: {
      type: Boolean,
      default: false
    },
    stripe: {
      type: Boolean,
      default: false
    },
    border: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      mergeLine: {},
      mergeIndex: {}
    }
  },
  methods: {
    handleAction(e, item) {
      console.log('编辑啊', e, item)
      this.$emit(e.event, item)
    },
    handleScope({ row, $index, column }) {
      return { row, $index, column }
    },
    clearSelection() {
      this.$refs.elTable.clearSelection()
    },
    toggleRowSelection(row, selected) {
      this.$refs.elTable.toggleRowSelection(row, selected)
    },
    toggleAllSelection() {
      this.$refs.elTable.toggleAllSelection()
    },
    toggleRowExpansion(row, expanded) {
      this.$refs.elTable.toggleRowExpansion(row, expanded)
    },
    setCurrentRow(row) {
      this.$refs.elTable.setCurrentRow(row)
    },
    clearSort() {
      this.$refs.elTable.clearSort()
    },
    clearFilter(columnKey) {
      this.$refs.elTable.clearFilter(columnKey)
    },
    doLayout() {
      this.$refs.elTable.doLayout()
    },
    sort(prop, order) {
      this.$refs.elTable.sort(prop, order)
    },
    currentChange(val) {
      this.$emit('p-current-change', val)
    },
    sizeChange(val) {
      this.$emit('size-change', val)
    }
  }
}

</script>
<style scoped lang="scss">
@import "@/styles/variables.scss";
.button {
  margin: 0 5px;
  padding: 0;
  border: none;
  background: none;
  color: $menuActiveText;
}

.danger {
  color: #f56c6c;
}

.table-pagination{
    margin-top: 15px;
    display: flex;
    justify-content: flex-end;
}
</style>

2.全局引入(main.js)

import CustomTable from '@/components/Table/table'
Vue.component('CustomTable', CustomTable)

3.mixin公用方法配置
(1)新建mixin文件
在这里插入图片描述
(2)tableMixin内容如下

/**
 * data中url定义 list为查询列表  delete为删除单条记录  deleteBatch为批量删除
 */
import { getAction, postAction, deleteAction } from '@/api/manage'
import { filterObj } from '@/utils/index'

export const tableMixin = {
  data() {
    return {
      /* 查询条件-请不要在queryParam中声明非字符串值的属性 */
      queryForm: {},
      /* 数据源 */
      dataSource: [],
      /* 分页参数 */
      pagination: {
        current: 1,
        pageSize: 10,
        pageSizeOptions: ['10', '20', '30'],
        showTotal: (total, range) => {
          return range[0] + '-' + range[1] + ' 共' + total + '条'
        },
        showQuickJumper: true,
        showSizeChanger: true,
        total: 0
      },
      /* table加载状态 */
      loading: false
    }
  },
  created() {
    if (!this.disableMixinCreated) {
      this.loadData()
    }
  },
  methods: {
    loadData(arg) {
      if (!this.url.list) {
        this.$message.error('请设置url.list属性!')
        return
      }
      // 加载数据 若传入参数1则加载第一页的内容
      if (arg === 1) {
        this.pagination.current = 1
      }
      var params = this.getQueryParams()
      this.loading = true
      getAction(this.url.list, params).then((res) => {
        if (res.code === 0) {
          this.dataSource = res.data.list || res.data
          if (res.data.total) {
            this.pagination.total = res.data.total
          } else {
            this.pagination.total = 0
          }
        } else {
          this.$message.warning(res.msg)
        }
      }).finally(() => {
        this.loading = false
      })
    },
    search(form) {
      this.queryForm = form
      this.loadData(1)
    },
    getQueryParams() {
      // 获取查询条件
      var param = this.queryForm
      param.page = this.pagination.current
      param.per_page = this.pagination.pageSize
      return filterObj(param)
    },
    selectionChange(selection) {
      if (selection.length) {
        this.show = {
          ...this.show,
          batch: true
        }
      } else {
        this.show = {
          ...this.show,
          batch: false
        }
      }
      this.table = {
        ...this.table,
        selection
      }
      console.log('selection', selection, this.show, this.table)
    },
    onClearSelected() {
      this.$refs.foxTable.$refs.elTable.clearSelection()
      this.table.selection = []
    },
    searchReset() {
      this.queryForm = {}
      this.loadData(1)
    },
    batchDel: function() {
      if (!this.url.deleteBatch) {
        this.$message.error('请设置url.deleteBatch属性!')
        return
      }
      if (this.table.selection.length <= 0) {
        this.$message.warning('请选择一条记录!')
        return
      } else {
        var ids = ''
        for (var a = 0; a < this.table.selection.length; a++) {
          ids += this.table.selection[a] + ','
        }
        var that = this
        this.$confirm({
          title: '确认删除',
          content: '是否删除选中数据?',
          onOk: function() {
            that.loading = true
            deleteAction(that.url.deleteBatch, { ids: ids }).then((res) => {
              if (res.success) {
                // 重新计算分页问题
                that.reCalculatePage(that.table.selection.length)
                that.$message.success(res.msg)
                that.loadData()
                that.onClearSelected()
              } else {
                that.$message.warning(res.msg)
              }
            }).finally(() => {
              that.loading = false
            })
          }
        })
      }
    },
    handleDelete: function(item) {
      const that = this
      if (!that.url.delete) {
        this.$message.error('请设置url.delete属性!')
        return
      }
      that.$confirm('确定要删除当前数据?', '提示', { type: 'warning' }).then(
        () => {
          postAction(that.url.delete, { id: item.id }).then((res) => {
            if (res.code === 0) {
              // 重新计算分页问题
              that.reCalculatePage(1)
              that.$message.success('删除成功')
              console.log('删除成功')
              that.loadData()
            } else {
              that.$message.warning(res.msg)
            }
          })
        }
      )
    },
    reCalculatePage(count) {
      // 总数量-count
      const total = this.pagination.total - count
      // 获取删除后的分页数
      const currentIndex = Math.ceil(total / this.pagination.pageSize)
      // 删除后的分页数<所在当前页
      if (currentIndex < this.pagination.current) {
        this.pagination.current = currentIndex
      }
      console.log('currentIndex', currentIndex)
    },
    handleEdit: function(record) {
      this.$refs.modalForm.show(record)
    },
    handleAdd: function() {
      this.$refs.modalForm.show()
    },
    // 分页改变
    handleTableChange(current) {
      this.pagination.current = current
      this.loadData()
    },
    // 分页总码改变
    handleSizeChange(size) {
      this.pagination.pageSize = size
      this.loadData()
    }
  }
}

(3)标注一下tableMixin里引入的内容

//  utils/index里的方法filterObj
//为了方便单独将方法放在这里展示,实际在所引入的文件里面
/**
 * 过滤对象中为空的属性
 * @param obj
 * @returns {*}
 */
export function filterObj(obj) {
  if (!(typeof obj === 'object')) {
    return
  }

  for (const key in obj) {
    if (obj.hasOwnProperty(key) &&
            (obj[key] === null || obj[key] === undefined || obj[key] === '')) {
      delete obj[key]
    }
  }
  return obj
}


// api/manage  文件的方法
//为了文章写的方便单独将方法放在这里展示,实际在所引入的文件里面
import axios from 'axios'

// post
export function postAction(url, parameter, cache = false, setExpireTime) {
  return axios({
    url: url,
    method: 'post',
    data: parameter
  })
}
// get
export function getAction(url, parameter, cache = false, setExpireTime) {
  return axios({
    url: url,
    method: 'get',
    params: parameter,
    cache,
    setExpireTime
  })
}

// deleteAction
export function deleteAction(url, parameter) {
  return axios({
    url: url,
    method: 'delete',
    params: parameter
  })
}

3.table里面的README.vue文件内容如下(以及使用说明):

# table 帮助文档使用说明

## 参数配置 

| 参数         | 类型    | 必填 | 说明                                                                            |
|--------------|---------|------|---------------------------------------------------------------------------------|
| columns      | array   | ✔️    | 表格列的配置描述,具体项见下表                                                  |
| data         | array   | ✔️    | 表格数据                                                                        |
| loading      | boolean |      | 是否正在加载,加载中不会显示任何行,默认false                                   |
| pagination   | boolean |      | 是否显示分页,默认false                                                        |
| current-page | number  |      | 当前分页数                                                                   |
| total        | number  |      | 数据总数                                                                      |
| page-size    | number  |      | 每次分页数                                                                        |

## column参数配置 

| 参数                   | 类型            | 必填 | 说明                                                                            |
|----------------------- |----------------|------|---------------------------------------------------------------------------------|
| fixed                  | string         |      | 定位   left/right                                                                |
| type                   | string         |      | 对应列的类型                                                                     |
| index                  | boolean        |      | 是否正在加载,加载中不会显示任何行,默认false                                      |
| column-key             | string         |      | column 的 key                                                                   |
| label                  | string         |      | 显示的标题                                                                       |
| prop                   | string         |      | 对应列内容的字段名                                                                 |
| width                  | number         |      | 对应列的宽度                                                                        |
| sortable               | boolean,string |      |默认false,对应列是否可以排序,如果设置为 'custom',则代表用户希望远程排序               |
| show-overflow-tooltip  | Boolean        |      |默认为true, 当内容过长被隐藏时显示 tooltip                                        |
| align                  | string         |      | 对齐方式, 默认center,  left/center/right                                           |
| header-align           | string         |      | 表头对齐方式, 默认center,left/center/right                                           |
| class-name             | string         |      | 列的 className                                                                    |
| label-class-name       | string         |      | 当前列标题的自定义类名                                                                  |

## 事件

| 事件名          | 触发时机                                           | 参数                                             |
|-----------------|----------------------------------------------------|--------------------------------------------------|
| p-current-change| 当currentPage 改变时会触发                          |                                                  |
| selection-change | 当行被选中或取消选中时触发                           |                                                 |
| size-change     | 当pageSize 改变时会触发                             |                                                  |

## 使用例子


已经全局引入,无需单个页面引入
    <template>
    <custom-table
        v-loading="table.loading"
        :column="table.column"
        :data="dataSource"
        pagination
        layout="total, sizes, prev, pager, next, jumper"
        :current-page.sync="pagination.current"
        :total="pagination.total"
        :page-size="pagination.pageSize"
        @p-current-change="handleTableChange"
        @selection-change="selectionChange"
        @size-change="handleSizeChange"
        @handleEdit="handleEdit"
        @handleDelete="handleDelete">
        </custom-table>
    </template>

    
```javascript
    <script>
        import {tableMixin} from '@/mixins/tableMixin'
        export default{
             mixins: [tableMixin],
             data(){
                return{
                    table: {
                        data: [],
                        column: [
                        	{
					            label: '操作',
					            prop: 'action',
					            fixed: 'right',
					            children: [
					              {
					                name: '编辑',
					                event: 'handleEdit'
					              },
					              {
					                name: '删除',
					                event: 'handleDelete'
					              }
					            ]
					          },
                            {
                                label: 'ID',
                                prop: 'id',
                                width: 80
                            },
                            {
                                label: '账号',
                                prop: 'username'
                            },
                        ], 
                        loading: false,
                    },
                    page: { //分页参数
                        pageNum: 1,
                        pageSize: 10,
                        total: 0
                    },
                     url: {
                        list: '', //列表请求接口路径
                    }
                }
             }
        }
    </script>



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值