天天看點

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是數組, 單選時是對象
           

封裝并不是很全面很精緻, 但是至少可以省點事~~~

以上代碼還未經過項目的檢驗, 屬于雛形, 還需要不斷的優化和改進, 如遇坑, 請留言. 謝謝!!!