vue 组件之element-ui table封装

做了这么久的后台管理系统,主要技术栈是vue,因此今天就分享一个二次封装element-ui的table(表格)组件,废话不多说了请看代码。。。。

该组件的封装使用render方法进行渲染。。。

<template>
  <div class="table-management">
    <el-table
      border
      style="width: 100%"
      :data="tblData"
      v-loading="tbLoading" 
      element-loading-text="正在加载"
      @selection-change="handleSelectionChange"
    >
      <el-table-column v-if="isSelect" type="selection" width="40">
      </el-table-column>
      <el-table-column
        v-for="(item, index) in column"
        :key="index"
        :type="item.type"
        :index="item.index"
        :column-key="item.columnKey"
        :label="item.label"
        :prop="item.prop"
        :width="item.width"
        :min-width="item.minWidth"
        :fixed="item.fixed"
        :header-align="item.headerAlign"
        :align="item.align"
        :show-overflow-tooltip="showOverflowTooltip"
      >
        <template  slot-scope="scope" slot="header">
        //表头显示icon可单独修改,我是默认添加的?icon,并展示相应的tips
        <div v-if="item.tip">
          <span>{{item.label}}</span>
          <el-tooltip placement="right">
            <div slot="content">
              <div v-for="(items,index) in item.tipData" :key="index">
                <p >
                    {{items.msg}}
                </p>
              </div>
            </div>
            <i class="el-icon-question"></i>
          </el-tooltip>
        </div>
         <p v-else>{{item.label}}</p>
        </template>
        <template slot-scope="scope">
          <expand-dom
            v-if="item.render"
            :render="item.render"
            :row="scope.row"
            :index="scope.$index"
            :column="item"
          ></expand-dom>
          <span v-else>{{ scope.row[item.prop]||'-' }}</span>
        </template>
      </el-table-column>
    </el-table>
    //分页封装
    <div class="pagination">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page.sync="curPage"
        :page-sizes="[10, 20, 30, 40]"
        :page-size="pageSize"
        :hide-on-single-page="total > 10 ? false : true"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      >
      </el-pagination>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    tblData: { type: Array },//表格数据list
    column: { type: Array },//表格展示的表头以及单元格字段
    isSelect: { type: Boolean, default: false },//是否显示选中组件
    total: { type: Number },//分页总条数
    currentPage:{type:Number,default:1},//分页--当前页
    tbLoading:{type:Boolean,default:false},//表格加载loading
    pageSize:{type:Number,default:10},//分页--每页显示条数,pageSizes已写死,如有变更可修改
  },
  components: {
    expandDom: {
      functional: true,
      props: {
        row: Object,
        render: Function,
        index: Number,
        column: {
          type: Object,
          default: null,
        },
      },
      render: (h, ctx) => {
        const params = {
          row: ctx.props.row,
          index: ctx.props.index,
        };
        if (ctx.props.column) params.column = ctx.props.column;
        return ctx.props.render(h, params);
      },
    },
  },
  data() {
    return {
      showOverflowTooltip: true,
    };
  },
  computed: {
    curPage:{
      get(){
        return this.currentPage
      },
      set(val){
        console.log(val);
        // this.$emit("handleCurrentChange", val);
      }
    }
  },
  methods: {
    //选中方法回调
    handleSelectionChange(val) {
      // 选中事件
      this.$emit("handleSelectBtn", val);
    },
    handleButton(methods, row, index) {
      // 按钮事件
      this.$emit("handleButton", { methods: methods, row: row, index: index });
    },
    //分页api(展示每页显示条数)
    handleSizeChange(val) {
      this.$emit("handleSizeChange", val);
    },
    //分页点击api(获取当前页数据)
    handleCurrentChange(val) {
      this.curPage = val;
      this.$emit("handleCurrentChange", val);
    },
  },
  mounted() {},
};
</script>
<style rel="stylesheet/scss" lang="scss"  scoped>
.table-management {
  .pagination {
    float: right;
    margin: 20px;
  }
  .imgBox {
    width: 50px;
    height: 50px;
    margin: 0 auto;
    img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>


下面是组件内部调用方法,以及使用心得:

  //详细参数可查看组件封装(上一代码块)
  //isSelect:是否显示选中组件
  //handleSelectBtn:选中方法回调
  //handleSizeChange:分页api(展示每页显示条数)
  //handleSizeChange:分页点击api(获取当前页数据)

<template>
 <div>
  <table-tem
   @handleSizeChange="handleSizeChange"
   @handleCurrentChange="handleCurrentChange"
   :tblData="tblData"
   :column="column"
   :isSelect="true"
   :total="total"
   @handleSelectBtn="handleSelectBtn"
   :currentPage="listQuery.page"
   :pageSize="listQuery.pageSize">
  </table-tem>
 </div>
</template>
<script>
//引入组件table
import tableTem from "@/components/tableTem";
//下面要格式化日期,所以引入moment插件,大佬可自己封装jsApi
import moment from 'moment'
 data(){
  return{
    tblData:[],//表格展示数据list,由接口获取
    selectList:[],//储存列表选中的数据
    total:0,//total:数据总条数,由接口返回
    listQuery:{//接口请求参数
     page:1,//表格显示当前页数
     pageSize:10//表格显示每页条数
    },
    column:[//表格展示列,也就是表头字段
      {
        prop: 'imgUrl',//表格渲染字段
        label: 'logo',//表头显示名字
        headerAlign: 'center',//表头样式-居中显示
        align: 'center',//单元格样式-居中显示
        minWidth:'110',//表头+单元格显示最小宽度
        render: this.renderImg//当前渲染字段api--列出显示img的api
      },
      {
        prop: 'timeList',
        label: '时间段',
        headerAlign: 'center',
        align: 'center',
        render: this.renderTimeList
      },
      {
        prop: 'type',
        label: '类型',
        headerAlign: 'center',
        align: 'center',
        render: this.renderType
      },
      {
        prop: 'StatusDesc',
        label: '状态',
        headerAlign: 'center',
        align: 'center',
        tip: true,//是否展示表头状态描述提示信息
        tipData: [//展示的提示信息数组
          {msg: '我是展示在状态表头里面的提示信息1'},
          {msg: '我是展示在状态表头里面的提示信息2'}
         ],
         minWidth: 150
       },
      {
        prop: 'createTime',
        label: '创建时间',
        headerAlign: 'center',
        align: 'center',
        minWidth:'90',
        render:this.renderCreateTime//当前渲染字段api--(后端返回的是时间戳需要前端处理一下)
      },
      //接下来就着重说一下表格的操作按钮(相同的字段前面都表述清楚了)
      {
        prop: 'operation',
        label: '操作',
        headerAlign: 'center',
        align: 'center',
        minWidth:'110',
        render: this.renderOperation//该方法是针对操作一列的按钮的api
       }
    ],
   }
 },
 methods:{
    //分页点击
    handleCurrentChange(val){
      this.listQuery.page=val
      //掉接口:获取表格数据接口
    },
    //获取每页显示条数
    handleSizeChange(val){
      this.listQuery.pageSize=val
      //掉接口:获取表格数据接口
    },
    // 列表选中回调api
    handleSelectBtn(val) {
      this.selectList=val;
    },
   //表格-单元格img渲染api
   renderImg(h, { row }){
      //row.imgUrl:imgUrl字段由数据返回
      if(row.imgUrl){
        return h(
          "img",
          {attrs: {//设置img的属性以及样式
            src: row.logoUrl,
            width:80,
            height:80
          }}
        );
      }else{
        return h(
          "div",
          {attrs: {
            width:80,
            height:80
          }}
        );
      }
    },
    //渲染时间数组
    renderTimeList (h, {row: {timeList}}) {
      let timeListArr = []
      for (let i of timeList) {
        timeListArr.push(i.startTime + '~' + i.endTime)
      }
      return h('div', timeListArr.map(function (item, index) {
        return h('div', {
        }, item)
      })
      )
    },
    // 状态渲染类
    renderType(h, { row }){
      let statusStr=''
      if(row.type == 1){
        statusStr='类型1'
      }else if(row.type== 2){
        statusStr='类型2'
      }else if(row.type== 3){
        statusStr='类型3'
      }else{
        statusStr=''
      }
      return h(
        "div",
        {},
        statusStr
      );
    }
    // 时间渲染api,由于列表字段比较多,所以日期+时间换行显示
    renderCreateTime(h, { row}) {
      if(!row.createTime){
        return ''
      }
      let t=moment(row.createTime).format('YYYY-MM-DD HH:mm:ss')
      let tArr=t.split(' ')
      //render方法返回的必须是一个数组包裹,下面展示的dom是:由一个div包裹的两个p标签
      return h(
        "div",
        {},[h("p",{style: {margin: 0}},tArr[0]),h("p",{style: {margin: 0}},tArr[1])]
      );
    }, 
    //下面是操作按钮一列
    // 操作
    renderOperation (h, {row}) {
      return h('div', {
      }, [
        //有几个按钮就在数组内部以数组元素的方式写入
        h('el-button', {//指定按钮样式
          props: {//element 按钮类型
            type: 'danger',
            icon: 'el-icon-edit'//指定按钮上的icon
          },
          style:{//按钮样式
            margin: '0px 0px 5px',
            padding:'8px',
            cursor: 'pointer',
            display:'block'
          },
          on: {//按钮回调方法
            click: () => {
              //此处写按钮回调方法
            }
          }
        }, '按钮名字1'),//按钮名字
        h('el-button', {
          props: {
            type: 'primary'
          },
          style:{
            margin: '0px 0px 5px',
            padding:'8px',
            cursor: 'pointer',
            display:'block'
          },
          on: {
            click: () => {
              //同上
            }
          }
        },'按钮名字2'),
        h('el-button', {
          props: {
            type: 'success'
          },
          style:{
            margin: '0px',
            padding:'8px',
            cursor: 'pointer',
            display:'block'
          },
          on: {
            click: () => {
              //同上
            } 
          }
        }, '按钮名字3'),
      ])
    },
 }
</script>

基本用法综上所述,由于时间观念就不做赘述了。。。

如有技术上的bug,欢迎各位技术大佬批评指正。。。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值