Vue + Element-UI管理系统中 Table表格 二次封装

前言:

项目中,使用vue + element 的后台管理系统中 用的table表格很多,而且大部分很相似,一遍遍的写,代码会变得很冗余,

于是利用Vue + Element  Table 重新封装出了一套表格组件。

 

下面是常见的table效果图:

包含页面跳转、属性过滤、图片、文字颜色显示、switch切换、操作栏等,

数据使用了 mockjs 创建

 

1. 在 component中 创建文件夹 talbeData 添加文件 index.vue

<template>
  <div class="app-container">
    <el-table
      :data="dataList"
      v-loading="loading"
      border
      fit
      highlight-current-row
      style="width: 100%;"
      @selection-change="handleSelectionChange"
      @sort-change="handleSortChange">
      <!-- 是否有多选 -->
      <el-table-column type="selection" width="55" v-if="table_config.isCheckBox"></el-table-column>
      <!-- 是否需要序号 -->
      <el-table-column type="index" label="序号" width="55" align="center" v-if="table_config.isIndex"/>

      <el-table-column
        v-for="item in table_config.thead"
        :key="item.prop" 
        :prop="item.prop" 
        :label="item.label"
        :min-width="item.minWidth"
        :sortable="item.sortable ? true : false"
        align="center">
        <template slot-scope="scope">
          <!-- 有状态过滤 -->
          <span v-if="item.filter" :class="item.specialClass && item.specialClass(scope.row)">
            {{item.callback && item.callback(scope.row)}}
          </span>
          <!-- 图片展示 -->
          <img v-else-if="item.image" :src="scope.row[item.prop]" style="width:40px; height: 40px">
          <!-- switch开关 -->
          <el-switch
            v-else-if="item.switch"
            v-model="scope.row[item.prop]"
            active-text="启用"
            active-value = 1
            inactive-value = 0
            inactive-text="停用"
            @change="item.callback && item.callback(scope.row)"
          >
          </el-switch>
          <!-- 有跳转 -->
          <router-link 
            v-else-if="item.router" 
            :to="{path: item.routerPath, query: {name: scope.row[item.prop]}}"
          >
            {{ scope.row[item.prop]}}
          </router-link>
          <!-- 默认展示 -->
          <span v-else>{{ scope.row[item.prop]}}</span>
        </template>
      </el-table-column>

      <!-- 操作列 -->
      <el-table-column
        fixed="right"
        :label="table_config.operation.label"
        :width="table_config.operation.width"
        align="center"
        v-if="isShow">
        <template slot-scope="scope">
          <template v-if="table_config.operation.cols">
            <div class="btn" 
              v-for="item in table_config.operation.cols.slice(0,2)" 
              :key="item.label">
              <el-button @click="item.handleRow(scope.row,item.label)" :type="item.type" size="small">
                {{item.label}}
              </el-button>
            </div>
          </template>
          <!-- 操作列超过3个,用更多下拉显示 -->
          <el-dropdown v-if="isShowOperationCols">
            <span class="el-dropdown-link">
              更多<i class="el-icon-arrow-down el-icon--right"></i>
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item 
                v-for="item in table_config.operation.cols.slice(2)" 
                :key="item.label" 
                @click.native="item.handleRow(scope.row,item.label)">
                {{item.label}}
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  props: {
    config: {
      type: Object,
      default: () => {}
    },
    dataList: {
      type: Array,
      default: () => {
        return []
      }
    },
    loading: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      table_config: {
        thead: [],            // 表格头
        isCheckBox: false,    // 是否多选
        isIndex: false,      // 是否有序号
        isOperation: true,   // 是否有操作列表
        operation: {        // 操作
          cols: []
        },      
      }
    }
  },
  computed: {
    isShow() {
      return this.table_config.isOperation && this.table_config.operation.cols.length
    },
    isShowOperationCols() {
      let list = this.table_config.operation.cols
      return list.length && list.length > 2
    }
  },
  watch: {
    // 监听传过来的config,进行初始化
    config: {
      handler(newVal) {
        if(newVal) {
          this.initConfig()
        }
      },
      immediate: true
    }
  },
  mounted() {
    
  },
  methods: {
    // 初始化配置
    initConfig() {
      for(let key in this.config) {
        if(Object.keys(this.table_config).includes(key)) {
          this.table_config[key] = this.config[key]
        }
      }
      
    },
    // 多选事件
    handleSelectionChange(val) {
      this.$emit('selection-change', val)
    },
    // 排序事件
    handleSortChange(val) {
      this.$emit('sort-change', val)
    }
  }
}
</script>

<style scoped>
.btn{
  display: flex;
  justify-content: center;
  display: inline-block;
  margin: 5px 0 0 10px;
}
.btn:first-child{
  margin-left: 0;
}
.color1{
  color: red;
}
.color2{
  color: green;
}
.color3{
  color: blue;
}
.el-dropdown{
  margin-left: 10px;
  cursor: pointer;
}
</style>

  

2.在组件中引用

<template>
  <div>
    <tableData 
      :config="table_config"
      :dataList="dataList"
      :loading="loading"
      @selection-change="selectionChange"
      @sort-change="sortChange"
    />

    <pagination
      :total="total"
      :pageNum.sync="pages.pageNum"
      :limit.sync="pages.pageSize"
      @pagination="fetchData()" 
    />
  </div> 
</template>

<script>
import { getList } from '@/api/table'
import TableData from '@/components/tableData';
import Pagination from '@/components/pagination';
import { sexType,roleType } from '../utils/config';

export default {
  components: {
    TableData,
    Pagination
  },
  data() {
    return {
      // 配置项
      table_config: {
        thead: [
          { 
            label: '姓名',
            prop: 'name',
            minWidth: '150px',
            router: true,
            routerPath: 'xxx'
          },
          {
            label: '性别',
            prop: 'sex',
            minWidth: '100px',
            filter: true,
            callback: (rowData) => {
              let data = sexType[rowData.sex]
              if(data) {
                return data.label
              }
            }
          },
          {label: '头像',prop: 'img',  minWidth: '100px',image: true},
          {label: '电话',prop: 'phone',minWidth: '150px',},
          {label: '时间',prop: 'time', minWidth: '200px',sortable: true},
          {
            label: '角色',
            prop: 'role',
            minWidth: '150px',
            filter: true,
            colorName: '',
            callback: (rowData) => {
              let data = roleType[rowData.role]
              if(data) {
                return data.label
              }
            },
            specialClass: (rowData) => {
              let data = roleType[rowData.role]
              if(data) {
                return data.className
              }
            }
          },
          {
            label: '状态',
            prop: 'status',
            minWidth: '150px',
            switch: true,
            callback: this.changeStatus
          },
        ],
        isCheckBox: true,
        isIndex: true,
        isOperation: true,
        // 表格操作列
        operation: {
          label: '操作',
          width: '200',
          cols: [
            {
              label: '编辑',
              type: 'primary',
              handleRow: this.handleRow
            },
            {
              label: '删除',
              type: 'danger',
              handleRow: this.handleRow
            }
          ]
        },
      },
      dataList: [],
      loading: false,
      pages: {
        pageNum: 1,
        pageSize: 10
      },
      total: 0
    }
  },
  mounted() {
    this.fetchData()
  },
  methods: {
    fetchData() {
      this.loading = true
      getList(this.pages).then(res => {
        if(res.data.code === 20000) {
          this.dataList = res.data.data.items
          this.total = res.data.data.total
          this.loading = false
        }
      })
      setTimeout(() => {
        this.loading = false
      },3000)
    },
     // 操作方法
    handleRow(rowData,label) {
      console.log(rowData,label);
    },
    // 多选方法
    selectionChange(val) {
      console.log(val);
    },
    // 排序方法
    sortChange(val) {
      console.log(val);
    },
    changeStatus(val) {
      console.log(val);
    }
  }
}
</script>

  

3.配置参数

table_config

参数说明类型默认值
thead 表格的列 Array []
isCheckBox 是否多选 Boolean false
isIndex 是否有序号 Boolean false
isOperation 是否有操作列 Boolean true
operation 操作列 Object -

配置列 thead

参数说明类型默认值
label 标题 string -
prop 字段名 string -
minWidth 最小宽度 string -
image 是否图片 Boolean false
sortable 是否排序 Boolean false
router 是否有跳转 Boolean false
filter 是否有信息过滤 Boolean false
switch 是否有开关 Boolean false
routerPath 跳转地址 string -

Table Events

参数说明类型默认值
selection-change 多选事件 Function -
sort-change 排序事件 Function -

table-column Events

参数说明类型默认值
callback 回调函数 Function(row) -
specialClass 特殊字体颜色函数 Function(row) -
handleRow 操作列回调函数 Function(row, label) -

源码

如果你感兴趣的话,请前往 GitHub 查看源码和完整文档。

https://github.com/wangibook/my-table-component

 

posted @ 2022-04-06 11:39  王大师  阅读(1464)  评论(0编辑  收藏  举报