Vue使用Element-ui封装全局公用table组件

更多精彩资源请访问我的个人博客:https://www.codelin.site

最近在工作中大哥让我修改一下所有页面的table组件 ,要求自己封装一个table组件,减少代码冗余。我们都知道后台便利系统需要大量用到table组件,每次都写基本相同的样式,会使得代码变得臃肿,所以自己对element-ui中的table组件进行二次封装。

最近在写公司后台管理项目时,大哥让我自己封装一个table组件,把页面组件都换了,代码好维护些。我们平时在使用element-ui中的table组件时,如果列多的话html结构将会变得非常臃肿,所以自己封装一个table组件来使用还是非常必要的。

接到任务我就开始着手准备了,我们都知道element的table中的column是我们用到的最多的,所以最先准备的就是配置column列的参数,然后使用v-for进行渲染,这就是基本的骨架了,我们可以看下面为l-table(自己组件的名字)的基本骨架。


<!-- 筛选器 -->
<div class="from-wraper">
  <el-form class="toolkit-box" :label-position="align" label-width="90px">
    <div class="toolkit-item">
      <slot name="toolkit"></slot>
    </div>
  </el-form>
  <el-form class="tookit-buttons">
    <slot name="toolkit-buttons"></slot>
  </el-form>
</div>
<!-- 表格 -->
<el-table
    :data="data"
    ref="mutipleTable"
    :stripe="options.stripe"
    @selection-change="options ?  options.mutiSelect.methods : false">
  <!--region 选择框-->
  <el-table-column
    v-if="options && options.mutiSelect.status"
    type="selection"
    label="全選"
    width="55">
  </el-table-column>
  <!-- 数据展开项 -->
  <el-table-column v-if="options.expand" type="expand">
    <template slot-scope="scope">
      <el-form class="faq-table-expand">
        <el-form-item class="faq-detail-title">
          <span>Q: {{ scope.row.title }}</span>
        </el-form-item>
        <el-form-item class="faq-detail-content">
          <span>A: {{ scope.row.suggestion }}。</span>
        </el-form-item>
      </el-form>
    </template> -->
  </el-table-column>
  <!-- 数据列 -->
  <template v-for="(column, index) in columns">
    <!-- 存在过滤项 -->
    <template v-if="column.filters">
      <el-table-column :prop="column.prop"
        :key='column.label'
        :label="column.label"
        :align="column.align"
        :min-width="column.minWidth"
        :sortable="column.sortable"
        :filters="column.filters"
        :filter-method="filterHandler"
        >
        <template slot-scope="scope">
          <template v-if="!column.render">
              <template v-if="column.formatter">
                  <span v-html="column.formatter(scope.row, column)"></span>
              </template>
              <template v-else>
                  <span>{{scope.row[column.prop]}}</span>
              </template>
          </template>
          <template v-else>
              <expand-dom :column="column" :row="scope.row" :render="column.render" :index="index" ></expand-dom>
          </template>
        </template>
      </el-table-column>
    </template>
    <!-- 不存在过滤项 -->
    <template v-else>
      <el-table-column :prop="column.prop"
        :key='column.label'
        :label="column.label"
        :align="column.align"
        :width="column.width"
        :sortable="column.sortable"
        >
        <template slot-scope="scope">
          <template v-if="!column.render">
              <template v-if="column.formatter">
                  <span v-html="column.formatter(scope.row, column)"></span>
              </template>
              <template v-else>
                  <span>{{scope.row[column.prop]}}</span>
              </template>
          </template>
          <template v-else>
              <expand-dom :column="column" :row="scope.row" :render="column.render" :index="index" ></expand-dom>
          </template>
        </template>
      </el-table-column>
    </template>
  </template>
  <!-- 按钮操作组 -->
  <el-table-column ref="fixedColumn" label="操作" align="center" :width="operates.width"
      v-if="operates.list.filter(_x=>_x.show === true).length > 0">
    <template slot-scope="scope">
    <div class="operate-group">
      <template v-for="(btn, key) in operates.list">
        <div class="item" v-if="btn.show" :key='btn.id'>
        <el-button :type="btn.type" size="mini" :icon="btn.icon" :disabled="btn.disabled"
          :plain="btn.plain" @click.native.prevent="btn.method(key,scope.row)">{{ btn.label }}
        </el-button>
        </div>
      </template>
    </div>
    </template>
  </el-table-column>
</el-table>
<!-- 分页 -->
<div class="paginartion_wraper">
  <el-pagination
      :page-size="pagination.size"
      @current-change="pagination.handleCurrentChang"
      :current-page.sync="pagination.page"
      layout="total, prev, pager, next"
      :total="pagination.total">
    </el-pagination>
</div>

我这里封装的比较全面,基本封装完成后所有页面的table都可以用到,我们着重说el-table的封装,我们都知道table除了column之外还没包含操作列,所以我们的参数主要用到了column(数据列)、operates(操作列)以及options(表格的基本配置)。

pagination: {
  size: 50,
  position: 'flex-end',
  total: 0,
  page: 1,
  handleCurrentChang: (val) => {
    this.handleCurrentChange(val)
  }
},
// table基本配置
options: {
  stripe: true,
  loading: true,
  highlightCurrentRow: true,
  mutiSelect: false,
  expand: true
},
// table列配置
columns: [
  COLUMNS.LABEL,
  COLUMNS.ID,
  COLUMNS.TITLE,
  COLUMNS.STATUS
],
// table操作列配置
operates: {
  width: 150,
  list: [
    {
      label: '編輯',
      type: 'text',
      show: true,
      disabled: false,
      method: (index, row) => {
        this.editFaq(row.id)
      }
    },
    {
      label: '禁用/發布',
      type: 'text',
      show: true,
      disabled: false,
      method: (index, row) => {
        this.publishFaq(row, index)
      }
    },
    {
      label: '刪除',
      type: 'text',
      show: true,
      disabled: false,
      method: (index, row) => {
        MessageBox.confirm('確認刪除嗎?此操作不可恢復!', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.removeFaq(row.id)
        })
      }
    }
  ]
},

这里比较主要的还是column里的数据怎么定义的。

有了骨架之后有了肌肉和血液才完美,所以上面提到的三个主要配置参数就用到了。options和operates都比较好理解,主要是column里的render函数比较难理解,我也是看了很久没弄明白,vue的render函数作用不太懂的同学自行去看文档吧。因为我也不懂,嘿嘿。利用好了这个render函数我们就可以在数据列中任意使用标签啦组件啦这些东西。

请看下面代码我是如何实现使用render函数实现多样化配置的:

export const COLUMNS = {
  LABEL: {
    prop: 'label', //对应的列
    label: '問題類型', //对应列的label
    align: 'center', //对齐方式
    width: 160, //宽度//灵魂就在于这里,使用render函数我们可以生成虚拟dom,可以生成标签组件等。
    render: (h, params) => {
      return h('el-tag', {
        props: { effect: 'plain' }
      }, params.row.label)
    }
  },
  ID: {
    prop: 'id',
    label: '問題ID',
    align: 'center',
    width: 170,
    render: tableRender.renderFilterId  //这是里自己封装的一个列数据组件
  },
  TITLE: {
    prop: 'title',
    label: '問題標題',
    align: 'center'
  },
  STATUS: {
    prop: 'status',
    label: '發布狀態',
    align: 'center',
    width: 100,
    render: (h, params) => {
      return h('el-tag', {
        props: {
          type: params.row.status === 'on' ? 'success' : 'info'
        }
      }, params.row.status === 'on' ? '已發布' : '未發布')
    }
  }
}

到了这里就差不多了,我们去试试新的组件好不好使

数据项里面所有有特殊格式的都是靠render函数来实现的。

本次table组件的封装可以实现数据多样化展示,所有table组件配置,数据多样化展示配置,操作按钮的配置均在上面提到的三个参数里面实现。总体来说通过这次的组件封装还是学到了很多东西的。如果有疑问欢迎来访我的博客互相交流:https://www.codelin.site/

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值