vue + element-ui 复杂表格组件封装,全局使用

1、需求场景
在实际的项目开发中,表格是使用最多的数据展示方式,如果每个页面都重写一遍表格代码,那么项目会变得越来越冗余,也不满足vue的设计理念,为了代码的简洁高效,可维护、可扩展,就需要封装table组件,全局调用

2、 参考element-ui,根据官方提供的api,进行代码的二次封装,将所需要的参数和方法封装暴露出去

<template>

  <div v-if="headerData.length">

    <el-table

      ref="elTable"

      size="small"

      width="100%"

      :border="border"

      :stripe="stripe"

      v-loading="loading"

      element-loading-text="数据加载中"

      element-loading-spinner="el-icon-loading"

      v-bind="$attrs"

      v-on="$listeners"

      :data="tableData"

      :height="height"

      :max-height="maxHeight"

      :row-key="getRowKeys"

      @sort-change="handleSort"

      @select="handleSelect"

      @select-all="handleSelectAll"

      @selection-change="handleSelectionChange"

      @filter-change="filterData"

    >

      <el-table-column

        v-if="radio"

        type="radio"

        :width="headerOptions.width"

        :fixed="headerOptions.fixed"

        align="center"

      >

        <template v-slot="scope">

          <el-radio

            v-model="selectedRadio"

            :disabled="!selectable(scope.row)"

            :label="scope.row[rowKey]"

            @change="handleRadioChange"

          >

            {{ '' }}

          </el-radio>

        </template>

      </el-table-column>

      <el-table-column

        v-if="selection"

        :reserve-selection="reserveSelection"

        type="selection"

        :selectable="selectable"

        :width="headerOptions.width"

        :fixed="headerOptions.fixed"

        align="center"

      ></el-table-column>

      <el-table-column

        v-if="index"

        type="index"

        label="序号"

        align="center"

        :width="headerOptions.indexWidth"

        :fixed="headerOptions.indexFixed"

      >

        <template v-slot="scope">

          <div class="text-center">

            {{ scope.$index + (currentPage - 1) * pageSize + 1 }}

          </div>

        </template>

      </el-table-column>

      <template v-for="column of headerData">

        <el-table-column

          v-if="column.children && column.children.length && column.visible !== false"

          :header-align="column.headerAlign || 'center'"

          :fixed="column.fixed"

          :min-width="column.minWidth"

          :key="column.prop"

          :label="column.label"

          v-bind="getColumnProps(column.columnProps)"

        >

          <template v-for="child of column.children">

            <el-table-column

              v-if="child.visible !== false"

              :header-align="child.headerAlign || 'center'"

              :fixed="child.fixed"

              :min-width="child.minWidth"

              :key="child.prop"

              :align="child.align"

              :width="child.width"

              :label="child.label"

              :prop="child.prop"

              :sortable="child.sortable"

              :formatter="child.formatter"

              :show-overflow-tooltip="child.overflow"

              v-bind="getColumnProps(child.columnProps)"

            >

              <template v-slot="scope">

                <table-content :context="scope" :config="child"></table-content>

              </template>

            </el-table-column>

          </template>

        </el-table-column>

        <el-table-column

          v-else-if="column.visible !== false"

          :header-align="column.headerAlign || 'center'"

          :min-width="column.minWidth"

          :fixed="column.fixed"

          :key="column.prop"

          :align="column.align"

          :width="column.width"

          :label="column.label"

          :prop="column.prop"

          :sortable="column.sortable"

          :formatter="column.formatter"

          :filters="column.filters"

          :filter-method="column.filterMethod"

          :column-key="column.columnKey"

          :show-overflow-tooltip="column.overflow"

          v-bind="getColumnProps(column.columnProps)"

        >

          <template v-slot="scope">

            <table-content :context="scope" :config="column"></table-content>

          </template>

        </el-table-column>

      </template>

    </el-table>

    <Pagination

      v-if="showPagination"

      v-bind="pageOptions"

      :single="single"

      :small="small"

      :current-page="currentPage"

      :page-size="pageSize"

      :total="total"

      @showPages="handleSize"

      @changePage="handlePage"

    />

  </div>

</template>



<script>

import Pagination from '@/components/Pagination'

import TableContent from './table-content'



export default {

  inheritAttrs: false,

  name: 'yq-table',

  props: {

    rowKey: {

      type: String,

      default: 'objId'

    },

    index: {

      default: true,

      type: Boolean

    },

    showPagination: {

      default: true,

      type: Boolean

    },

    showIndex: {

      default: true,

      type: Boolean

    },

    border: {

      default: true,

      type: Boolean

    },

    stripe: {

      default: true,

      type: Boolean

    },

    reserveSelection: {

      default: false,

      type: Boolean

    },

    pageOptions: {

      type: Object,

      default: () => {}

    },

    options: {

      type: Object,

      default: () => {}

    },

    currentPage: {

      type: Number,

      default: 1

    },

    pageSize: {

      type: Number,

      default: 10

    },

    selectable: {

      type: Function,

      default: _ => _

    },



    radio: Boolean,

    single: Boolean,

    small: Boolean,

    selection: Boolean,

    loading: Boolean,

    tableData: Array,

    total: Number,

    height: [String, Number],

    maxHeight: [String, Number],

    headerData: Array

  },

  data() {

    return {

      selectedRadio: ''

    }

  },

  computed: {

    headerOptions() {

      const baseOpts = {

        width: '60px',

        fixed: false,

        indexWidth: '60px',

        indexFixed: false

      }

      return Object.assign({}, baseOpts, this.options)

    }

  },

  methods: {

    getRowKeys(row) {

      return row.id

    },

    getColumnProps(val) {

      if (typeof val !== 'object') return null

      return val

    },

    handleRadioChange(val) {

      const item = this.tableData.filter(i => i[this.rowKey] === val) || []

      this.$emit('select-change', item)

    },

    handleSort(column, prop, order) {

      this.$emit('table-sort', column, prop, order)

    },

    handleSelectionChange(val) {

      this.$emit('select-change', val)

    },

    filterData(val) {

      console.log(val)

      this.$emit('filter-data', val)

    },

    handleSelectAll(val) {

      this.$emit('select-all', val)

    },

    handleSelect(val, row) {

      this.$emit('select', val, row)

    },

    handlePage(val) {

      this.$emit('now-page', val)

    },

    handleSize(val) {

      this.$emit('now-size', val)

    }

  },

  components: {

    TableContent,

    Pagination

  }

}

</script>

3、所要使用的地方引入组件

import Table from '@/components/Table'

components: {  Table  }

tableData:[],

tableHeader :[

      {

        label: '名称',

        prop: 'applyName',

        align: 'center',

        overflow: true

      },

]

.

.

需要传递给组件的参数在data中定义,接口赋值后组件接收渲染dom节点

// 获取列表数据

    getTableData() {

      this.loading = true

      this.getTableParams()

      highQualityPage(this.tableParams)

        .then(res => {

          this.loading = false

          this.tableData = res.result

          for (let i = 0; i < this.tableData.length; i++) {

//接口获取数据

            this.tableData[i].id = this.tableData[i].applyId

            this.tableData[i].dispatchStatus =

              this.tableData[i].dispatchStatus == '' ? false : this.tableData[i].dispatchStatus

            this.tableData[i].execStatusName =

              this.executionStatus.find(item => item.value == this.tableData[i].execStatus)

                ?.label || '--'

          }

          this.total = res.total

        })

        .catch(() => {

          this.loading = false

        })

    },

4、文章小结

因为表格组件是开发人员不可绕过的功能,也是使用最多的功能组件,所以为了使项目简洁高效,封装是必不可少的,项目中各种需求层出不穷,所以也需要我们开发人员考虑健全,尽可能做到组件高可扩展性,这样也才能提高开发效率。有疑问的朋友可以私我,咱们共同探讨。

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aotman_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值