table表格封装

封装el-table

  • 目前在编写项目中,每个页面都有el-table,所以对el-table做了二次封装, 组件在个人开发使用不错,但不确定能满足各种业务需求,所以这里主要和大家分享一下设计思路。用一次爽一次,越用越爽。
分析问题:
  • el-table是element-ui库的表单组件,如果我们要将其进行二次封装,那么需要考虑几个问题:
  • 动态表头
  • 嵌套表头
  • 表格显示内容类型自定义(文字,图片,超链接等)
  • 表格和分页联动
  • 表格事件的处理
  • 等等.
动态表头实现。

正常情况下,我们使用table:

 <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="date"
        label="日期"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址">
      </el-table-column>
 </el-table>

那由此我们可以设计出封装后样子:

      <el-table-column
        v-for="(item,index) in fieldList"
        :key="index"
        :prop="item.prop"
        :label="item.label"
        :width="item.width"
      >
      </el-table-column>
  • 更多实现:表格显示内容、自定义、事件等等(请看↓↓组件内部)。
  • 组件使用方法:( 请查看《table表格API》)。
  • 依赖分页组件,要使用分页功能必须要有分页组件(请查看《page分页分装》)。
组件内部template:
<template>
  <div class="Table">
    <el-table
      :data="data"
      :max-height="maxHeight"
      :row-class-name="rouClassNameFn"
      :stripe="stripe"
      border
      @selection-change="SelectionChange"
      style="width: 100%">
      <!--是否显示序号-->
      <el-table-column
        v-if="isIndex"
        label="序号"
        fixed
        width="50">
        <!--自定义序号-->
        <template v-slot="scope">
          <!--索引 + 1 + (当前页数 - 1) * 每页条数-->
          <span>{{scope.$index + 1 + (ispage.currentPage - 1) * ispage.pageSize }}</span>
        </template>
      </el-table-column>
      <!--是否显示多选框-->
      <el-table-column
        v-if="ischeckBox"
        type="selection"
        fixed
        width="50">
      </el-table-column>
      <!--是否显示单选框-->
      <el-table-column
        v-if="isRadio"
        fixed
        label="选择"
        width="50">
        <template scope="scope">
          <div @click="radioChange($event,scope.row)">
            <el-radio :label="scope.$index" v-model="radio">{{""}}</el-radio>
          </div>
        </template>
      </el-table-column>
      <!--渲染列表-->
      <el-table-column
        v-for="(item,index) in fieldList"
        :prop="item.prop"
        :label="item.label"
        :align="item.align"
        :key="index"
        :fixed="item.fixed"
        :min-width="item.minWidth"
        :show-overflow-tooltip="showTooltip"
        :formatter="item.formatter"
      >
        <template v-slot="scope" v-if="!item.formatter">
          <!-- solt 自定义列(具名插槽) v-solt 简写 # -->
          <template v-if="item.type === 'slot'">
            <slot
              :name="'col-' + item.prop"
              :row="scope.row"
            />
          </template>
          <!-- 标签 -->
          <el-tag v-else-if="item.type === 'tag'"
                  v-for="(childitem,idx) in scope.row[item.prop]"
                  :key="idx"
                  style="margin-right: 10px;"
          >
            {{childitem}}
          </el-tag>
          <!-- 图片 -->
          <img
            v-else-if="item.type === 'img'"
            height="50px"
            :src="scope.row[item.prop]"
          >
          <!-- 超链接 -->
          <el-link v-else-if="item.type === 'href'"
                   :href="hrefValue?scope.row[item.prop][hrefValue.url]:scope.row[item.prop]"
                   :underline="false"
                   target="_blank">
            {{hrefValue?scope.row[item.prop][hrefValue.name]:scope.row[item.prop]}}
          </el-link>
          <!-- 路由跳转 -->
          <el-link type="primary"
                   v-else-if="item.type === 'router'"
                   @click="routerClickFn(scope.row)"
                   :underline="false"
          >
            {{scope.row[item.prop]}}
          </el-link>
          <!-- 其他 -->
          <span v-else class="text">
           {{scope.row[item.prop]}}
          </span>
        </template>
      </el-table-column>
      <!-- 操作 -->
      <el-table-column
        v-if="handle"
        :fixed="handle.fixed"
        align="center"
        :label="handle.label"
        :width="handle.width"
      ><template v-slot="scope">
          <template>
            <!-- 自定义操作类型 -->
<!--            <slot-->
<!--              v-if="handle.slot"-->
<!--              :name="'bt'"-->
<!--              :row="scope.row"-->
<!--            />-->
            <!-- 操作按钮 -->
            <el-button
              v-for="(item,idx) in handle.btList"
              v-if="!handle.slot"
              :key="idx"
              size="mini"
              :type="item.type"
              :icon="item.icon"
              @click="handleClick(item.label, scope.row)"
            >
              {{ item.label }}
            </el-button>
          </template>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页组件 -->
    <div class="page" v-if="ispage">
      <wb-page :data="params"
               @currentChange="currentChangeFn"
               @sizeChange="sizeChangeFn"
      ></wb-page>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'Table',
    props:{
      // 渲染的表格数据
      data: {
        type: Array,
        default: () => {
          return []
        }
      },
      //  表格的最大高度
      maxHeight: {
        type: String,
      },
      // 是否添加斑马线
      stripe: {
        type: Boolean,
        default: true
      },
      // 是否显示序号
      isIndex: {
        type: Boolean,
        default: false
      },
      // 是否有选择框
      ischeckBox: {
        type: Boolean,
        default: false
      },
      // 是否有单选框
      isRadio: {
        type: Boolean,
        default: false
      },
      // 是否超出隐藏,移入显示全部内容
      showTooltip: {
        type: Boolean,
        default: true
      },
      // 表格字段配置
      fieldList: {
        type: Array,
        default: () => {
          return []
        }
      },
      // 操作栏配置
      handle: {
        type: Object
      },
      // 是否显示分页分页参数
      ispage: {
        type: Object,
      },
      //  超链接如果是对象自定义 字段名value
      hrefValue: {
        type: Object,
      }
    },
    data () {
      return {
        // 单选框索引
        radio: 0,
        // 分页参数
        params: {
          background:this.ispage.background,
          hideOnSinglePage:this.ispage.hideOnSinglePage,
          pageSize:this.ispage.pageSize,
          pageSizes:this.ispage.pageSizes,
          total:this.ispage.total,
          currentPage:this.ispage.currentPage,
          layout:this.ispage.layout,
        }
      }
    },
    methods:{
      // 拿到索引
      rouClassNameFn ({row,rowIndex}){
        row.index = rowIndex;
        this.$emit('rouClassNameEvent',row)
      },
      // 多选触发事件
      SelectionChange (val) {
        this.$emit('SelectionChange',val)
      },
      // 单选触发事件
      radioChange (e,val) {
        if (e.target.tagName === 'INPUT') return;
        this.$emit('radioChange',val)
      },
      // 点击操作触发事件
      handleClick (eventName,row){
        let val = {
          eventName:eventName,
          row:row,val
        };
        this.$emit('handleClick',val)
      },
      // 页数改变时候触发
      currentChangeFn (val) {
        this.ispage.currentPage = val; // 当前页
        this.$emit('currentChange',val)
      },
        // 选择每页显示多少条的时候触发(设置选择器后,才生效)
      sizeChangeFn (val){
        this.ispage.pageSize = val // 每页显示多少条
        this.$emit('sizeChange',val)
      },
      //  点击路由跳转
      routerClickFn (row) {
        // console.log(row)
        this.$emit('routerClick',row)
      }
    }
  }
</script>

<style scoped>
  .page{
    margin-top: 50px;
  }
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值