vue2/vue3 二次简易封装Element-Table组件


一、背景

在管理系统的开发当中,页面顶部是一个表单筛选,中间是一个表格展示数据,页面底部是一个分页器,这种页面结构出现的频率很高。如图:

在这里插入图片描述

二、组件封装(vue2)
<template>
<div>
   <div v-if="isShow">
      <slot name="filterForm"></slot>// 表单筛选插槽
    </div>
    <div v-if="isShow">
      <slot name="middleButtons"></slot>//如图上所示的 导出、刷新按钮插槽
    </div>
    <el-table :data="operateList"  border ref="table" v-loading="loading">//表格
      <el-table-column type="index" label="#" align="center" width="60px" />
      <template v-for="(item, index) in tableList">
          <el-table-column :prop="item.prop" :label="item.label" align="center" :width="item?.width || '100px'">
      </template>
       <el-table-column label="操作"  align="center" v-if="operation" :width="operateWidth" fixed="right">
            <template slot-scope="scope">
              <slot :row="scope.row"></slot> //表格操作栏按钮插槽
            </template>
       </el-table-column>
    </el-table>
    <div v-if="isShowPagination">//分页
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currPage"
       :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total">
      </el-pagination>
    </div>
</div>
</template>
<script>
export default {
  data() {
    return {
      currPage: 1,
      pageSize: 10,
    }
  },

  props: {
    isShow: {// 是否使用筛选
      type: Boolean,
      default: true
    },
    loading: {    // loading效果
      type: Boolean,
      default: false
    },
    operateList: {  // 数据源
      type: Array,
      default: () => []
    },
    tableList: { // label和prop
      type: Array,
      default: () => []
    },
    operation: {// 是否需要没有展开行的右侧操作栏
      type: Boolean,
      default: false
    },
    total: {// 总表格条数
      type: Number,
      default: 0
    },
    isShowPagination: {//  是否需要分页
      type: Boolean,
      default: true
    },
    pageSizes: { //分页每页显示条数
      type: Array,
      default: () => [10, 25, 50, 100, 300]
    },
    operateWidth: {  //操作栏宽度大小
      type: Number,
      default: 252
    },
    tableCurrent: {   //分页当前页
      type: Number,
      default: 1
    },
    tablePageSize: {   //分页一页显示条数
      type: Number,
      default: 10
    },
  },
  methods: {
    handleSizeChange(v) {
      this.pageSize = v
      this.currPage = 1
      this.$emit('getTableList', {
        currPage: this.currPage,
        pageSize: this.pageSize
      })
    },
    handleCurrentChange(v) {
      this.currPage = v
      this.$emit('getTableList', {
        currPage: this.currPage,
        pageSize: this.pageSize
      })
    },
  },
  watch: {},
  mounted() {
    this.currPage = this.tableCurrent
    this.pageSize = this.tablePageSize
  }
}
</script>
使用举例
<template>
  <my-table operateList="tableData" :loading="tableLoading" :tableList="tableList" :operation="true" :total="total"     :isShow="false" @getTableList="getTableList">
    <el-table-column label="操作">
         <template slot-scope="scope">
           <el-button type="info">详情</el-button>
        </ template >
 </my-table>
</template>
<script>
import MyTable from './MyTable .vue';
export default {
  data() {
    return {
       tableList: [
         {
          prop: 'name',
          label: '名称',
          width: '150'
        },
       ],
       tableData:[],
       tableLoading:false,
       total:10, 
    },
    methods:{
    getTableList(){ // 获取tableData }
    }
   }
 }
</script>
扩展

在此基础上,可以增加单选多选( type=“selection”)、展开行(extend)等等…

三、组件优化: 对要特殊处理的表格列进行优化,简化组件中使用的参数
<template>
  <div class="table">
    <el-table ref="table" :data="tableData" v-loading="tableLoading" border element-loading-text="获取数据中..."
      empty-text="暂无数据">
      <template v-for="(col, index) in tableColumn" :key="index">
        <!-- 序号 -->
        <el-table-column type="index" v-if="col.type === 'index'" :width="col.width" :label="col.label"  align="center" />
          <!-- 多选 -->
        <el-table-column type="selection" v-else-if="col.type === 'selection'" :width="col.width" align="center"/>
        <!-- 扩展插槽 -->
        <el-table-column type="expand" v-if="col.type === 'expand'" :width="col.width" :label="col.label">
          <template #default="{ row, $index }">
            <slot :row="row" :name="col.slot" :index="$index"></slot>
          </template>
        </el-table-column>
        <!-- 渲染插槽 -->
        <el-table-column :prop="col.prop" :label="col.label" align="center" v-else
          :show-overflow-tooltip="col.showOverflowTooltip" :min-width="col?.width || 100" :fixed="col.fixed">
          <template #default="{ row, $index }">
            <div class="colCell">
              <slot v-if="col.slot" :name="col.slot" :row="row" :index="$index" />
              <span v-else>{{ row[col.prop] }}</span>
            </div>
          </template>
        </el-table-column>
      </template>
    </el-table>
  </div>
  <div class="bottomPagination">
    <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currPage"
      v-if="isPagination" :page-size="pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total"
      :page-sizes="pageSizes">
    </el-pagination>
  </div>
</template>
<script setup>
import { ref, defineProps, defineEmits } from "vue";
const currPage = ref(1);
const pageSize = ref(10);
const multipleSelection = ref([]);
const funcEmit = defineEmits(['getTableData']);
defineProps({
  tableLoading: {
    type: Boolean,
    default: false
  },
  tableData: { //数据源
    type: Array,
    default: () => []
  },
  tableColumn: {//表格列
    type: Array,
    default: () => []
  },
  total: { //总表格条数,在需要分页时使用并必传
    type: Number,
    default: 0
  },
  isPagination: { //是否需要分页
    type: Boolean,
    default: false
  },
  pageSizes: { //分页每页显示条数
    type: Array,
    default: () => [10, 25, 50, 100, 300]
  },
})
// 分页器
const handleSizeChange = (val) => {
  pageSize.value = val;
  funcEmit('getTableData', {
    currPage: currPage.value,
    pageSize: val
  })
}
const handleCurrentChange = (val) => {
  currPage.value = val;
  funcEmit('getTableData', {
    currPage: val,
    pageSize: pageSize.value
  })
}
// 多选
const handleSelectionChange = (val) => {
  multipleSelection.value = val
}
</script>
组件使用
<template>
 <Table :tableColumn="tableColumn" :tableData="tableData">
      <template #date="{ row }">
        <span>{{ row.date}}</span>//根据需求调整日期格式
      </template>
      <template #expand="{ row }">
        <span>{{ row.address }}</span>
      </template>
      <template #action="{ row, index }">
        <el-button type="success">添加</el-button>
        <el-button type="warning">删除</el-button>
      </template>
  </Table>
</template>  
<script setup>
import Table from '@/components/VTable/index.vue'
const tableData = [
  {
    date: 1660737564000,
    name: '佘太君',
    address: '上海市普陀区金沙江路 1516 弄'
  },
  {
    date: 1462291200000,
    name: '王小虎',
    address: '上海市普陀区金沙江路 1517 弄'
  },
  {
    date: 1462032000000,
    name: '王小帅',
    address: '上海市普陀区金沙江路 1519 弄'
  },
  {
    date: 1462204800000,
    name: '王小呆',
    address: '上海市普陀区金沙江路 1516 弄'
  }
]
const tableColumn = [
  { type: 'index', label: 'NO.', width: '80'},
  { type: 'selection', width: '60'},
  { prop: 'name', label: '名字' },
  { prop: 'date', label: '日期', slot: 'date' },
  { prop: 'address', label: '地址', showOverflowTooltip: true },
  { type: 'expand', label: '详情', slot: 'expand', width: '80' },
  { prop: 'action', label: '操作', slot: 'action', fixed: 'right' },
]
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值