vue+element对常用表格的简单封装

在后台管理和中台项目中, table是使用率是特别的高的, 虽然element已经有table组件, 但是分页和其他各项操作还是要写一堆的代码, 所以就在原有的基础上做了进一步的封装

所涵盖的功能有: 内容展示 , 操作栏 , 选择框 , 分页 , 图片渲染 , 开关 , 过滤器(时间格式化)

直接上代码

组件:

<template>
  <div class="hello">
    <el-table
      :data="tableData"
      style="width: 98%"
      @selection-change="handleSelectionChange"
      border>
      <el-table-column v-if="type=='checkbox'" label="选择">
        <template slot-scope="{ row }">
          <el-checkbox v-model="row.isChecked" @change="handleChecked(row)"></el-checkbox>
        </template>
      </el-table-column>
      <el-table-column v-if="type=='selection'" :reserve-selection="true" type="selection" width="55" />
      <el-table-column v-if="type=='index'" type="index" label="序号" width="55" />
      <template v-for="(item, index) of tableTitle">
        <el-table-column
          :prop="item.prop"
          :label="item.label"
          :key="index"
          :min-width="item.width"
        >
          <template slot-scope="{ row, $index }" style="height: 100%;">
            <span v-if="item.filter == 'date'">
              {{ row[item.prop] | dateFilter }}
            </span>
            <span v-else-if="item.filter == 'time'">
              {{ row[item.prop] | timeFilter }}
            </span>
            <span v-else-if="item.filter == 'image' && row[item.prop]">
              <img :src="row[item.prop]" alt="" style="height: 45px;">
            </span>
            <span v-else-if="item.filter == 'switch'">
              <el-switch
                v-model="row[item.prop]"
                @change="change(row, $index)"
              />
            </span>
            <span v-else>
              {{ row[item.prop] }}
            </span>
          </template>
        </el-table-column>
      </template>
<!--      插槽: 操作-->
      <el-table-column label="操作" v-if="ishandle" :width="handleWidth">
        <template slot-scope="scope">
          <slot name="handle" :row="scope.row" :index="scope.$index"></slot>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      background
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      :page-size="pageSize"
      :current-page.sync="current"
      :page-sizes="[10, 20, 30, 40, 50, 100]"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      >
    </el-pagination>

  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    handleWidth: { // 操作宽度
      default: 200
    },
    ishandle: { // 是否有操作按钮
      type: Boolean,
      default: true
    },
    type: String, // 单选/多选/或值展示
    tableTitle: Array, // 表头
    tableData: Array, // 数据
  },
  data () {
    return {
      total: 1000,
      pageSize: 10,
      current: 1
    }
  },
  methods: {
    handleSizeChange (size) { // 改变每页数量
      this.pageSize = size
      this.$emit('handleChange', this.pageSize, this.current)

    },
    handleChecked (row) { // 单选
      if (row.isChecked) {
        this.tableData.map(item => {
          if (item.id != row.id) {
            this.$set(item, 'isChecked', false)
          }
        })
        this.$emit('handleChecked', row)
      } else {
        this.$emit('handleChecked', '', row)
      }
    },
    handleSelectionChange (row) { // 多选
      this.$emit('handleChecked', row)
    },
    handleCurrentChange (current) { //换页
      this.current = current
      this.$emit('handleChange', this.pageSize, this.current)
    },
    change (row, index) { // 切换开关
      this.$emit('handleSwitch', row, index)
    },
  }
}
</script>

<style scoped lang="scss">
</style>

在父组件中调用:

<template>
  <div class="home">
    <ComTable
      :handleWidth="200"
      :tableTitle="tableTitle"
      :tableData="tableData"
      @handleChange="handleChange"
      @handleSwitch="handleSwitch"
      @handleChecked="handleChecked"
    >
      <template slot="handle" slot-scope="scope">
        <el-button type="text" size="small">编辑{{scope.index}}</el-button>
      </template>
    </ComTable>
  </div>
</template>

<script>
import ComTable from '@/components/Com_Table.vue'

export default {
  name: 'Home',
  components: {
    ComTable
  },
  data () {
    return {
      tableTitle: [{
        prop: 'name',
        label: '姓名',
        width: '200',
      },{
        prop: 'sex',
        label: '性别',
        width: '200',
        filter: 'switch',
      },{
        prop: 'url',
        label: '头像',
        width: '200',
        filter: 'image',
      },{
        prop: 'date',
        label: '出生日期',
        width: '200',
        filter: 'date'
      },],
      tableData: [{
        id: 1,
        name: '张三',
        sex: true,
        url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3202059567,1723387850&fm=26&gp=0.jpg',
        date: new Date()
      },{
        id: 2,
        name: '张三',
        sex: true,
        url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3202059567,1723387850&fm=26&gp=0.jpg',
        date: new Date()
      },{
        id: 3,
        name: '张三',
        sex: true,
        url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3202059567,1723387850&fm=26&gp=0.jpg',
        date: new Date()
      },{
        id: 4,
        name: '张三',
        sex: true,
        url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3202059567,1723387850&fm=26&gp=0.jpg',
        date: new Date()
      },],
    }
  },
  mounted() {
  },
  methods: {
    handleChange (size, current) {
      // 分页改变时的回调----   size: 每页的数量   current: 第几页
      console.log(size, current, 'tableData')
    },
    handleSwitch (row, index) {
      // 切换开关时的回调-========   this.tableData: 滑块值改变后的数据.row: 当前行数据 index: 当前行的索引
      console.log(this.tableData, '--tableData---', row, index)
    },
    handleChecked (val) {
      // 勾选时的回调----   val: 选中的数据  多选是val是数组, 单选时是对象
      console.log(val, 'val===')

    }
  }
}
</script>

组件中有使用过滤器, 可以定义一下全家的过滤器,然后引入, 这里要根据自己的文件来进行调整. 送上我这里用的两个过滤器

// 注册全局的过滤器  {{ msg | dateFilter }}
import Vue from 'vue'
import moment from 'moment'

// 展示日期格式: YYYY-MM-DD
Vue.filter('dateFilter', function (dataStr, pattern = 'YYYY-MM-DD') {
  if (dataStr) {
    return moment(dataStr).format(pattern)
  } else {
    return dataStr
  }
})

// 展示日期格式: YYYY-MM-DD HH:mm:ss
Vue.filter('timeFilter', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
  if (dataStr) {
    return moment(dataStr).format(pattern)
  } else {
    return dataStr
  }
})

下面是相关参数的说明:

type: 表格类型. 非必传. 值: selection(多选) / checkbox(单选) 类型: string /index:序号1.2.3...

handleWidth: 操作栏宽度    非必传   默认200

tableTitle: 表头.  必传.   类型: 数组   例:
    tableTitle: [{
        prop: 'name',  绑定的字段
        label: '姓名',   表头名称
        width: '200',   列宽度
        filter: 'date'    过滤器. 需要展示的类型. 非必传.  值:
            date: 日期格式(YYYY-MM-DD)
            time: 时间格式(YYYY-MM-DD : HH:mm:ss)
            image: 图片
    }]

> tableData: 要展示的数据. 必传   类型: array   例:

插槽:

  slot="handle":    handle: 插槽名称
  slot-scope="scope":    scope: 组件传递给插槽的值  scope.row:  当前行的内容  scope.index: 当前行的索引

事件:

handleChange (size, current) {}, //分页改变时的回调----   size: 每页的数量   current: 第几页
handleSwitch (row, index) {}, // 切换开关时的回调-========   this.tableData: 滑块值改变后的数据.row: 当前行数据 index: 当前行的索引
handleChecked (val) {},  // 勾选时的回调----   val: 选中的数据  多选是val是数组, 单选时是对象

封装并不是很全面很精致, 但是至少可以省点事~~~

以上代码还未经过项目的检验, 属于雏形, 还需要不断的优化和改进, 如遇坑, 请留言. 谢谢!!!

posted @ 2020-12-28 17:05  dear嫑闹  阅读(1484)  评论(1编辑  收藏  举报