vue3封装多个标题的table,案例是2个

文章介绍了如何在Vue项目中使用TS编写一个可配置的table.vue组件,展示了如何动态生成列、处理分页以及响应式地从父组件接收数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建一个table. vue组件

<template>
  <div :class="tableData.config?.headerName?'tableTitle mt10':'tableTitle'" v-if="tableData.config?.headerName">{{tableData.config.headerName}}</div>
  <el-table
    v-loading="tableData?.config?.loading"
    :data="tableData.data"
    style="width: 100%;"
    :class="tableData.config?.headerName?'':'mt10'"
    :span-method="({ row, column, rowIndex, columnIndex }) => objectSpanMethod({ row, column, rowIndex, columnIndex })"
  >
    <el-table-column
      v-for="(item, index) in tableData.header"
      :key="index"
      :prop="item[0].key"
      :width="item[0].width"
      :label="item.length != 1 ? item[0].title : ''"
      :align="item[0].align || 'left'"
    >
      <el-table-column v-if="item.length == 1">
        <el-table-column :prop="item[0].key" :width="item[0].width" :label="item[0].title" :align="item[0].align || 'left'" />
      </el-table-column>
      <el-table-column v-else-if="item.length == 2">
        <el-table-column :prop="item[1].key" :width="item[1].width" :label="item[1].title" :align="item[1].align || 'left'" />
      </el-table-column>
      <el-table-column
        v-else-if="item.length == 3"
        :prop="item[1].key"
        :width="item[1].width"
        :label="item[1].title"
        :align="item[1].align || 'left'"
      >
        <el-table-column :prop="item[2].key" :width="item[2].width" :label="item[2].title" :align="item[2].align || 'left'" />
      </el-table-column>
    </el-table-column>
  </el-table>
  <!-- config.total不写的时候 不显示分页 -->
  <el-pagination
    v-if="tableData.config?.total != null"
    small
    :current-page="state.page.pageNum"
    :page-size="state.page.pageSize"
    :pager-count="5"
    :page-sizes="[10, 20, 30]"
    :total="tableData.config.total"
    layout="total, sizes, prev, pager, next, jumper"
    background
    @size-change="onHandleSizeChange"
    @current-change="onHandleCurrentChange"
  >
  </el-pagination>
</template>

<script lang="ts" setup>
import { reactive, defineAsyncComponent } from 'vue'

// 定义父组件传过来的值
const props = defineProps({
  tableData: {
    type: Object,
    default: () => {
      return {
        data: [], // 列表数据(必传)
        header: [], //表头内容(必传,注意格式)
        config: {
          fileName: '',  // 文件名
          headerName: '',  // 表头
        }, // 配置项(必传)
      }
    },
  },
})
const state = reactive({
  page: {
    pageNum: 1,
    pageSize: props?.tableData?.config?.params?.Count | 10,
  },
})
// 监听分页变化
watch(
  () => state.page,
  () => {
    let { pageNum, pageSize }: any = state.page
    let Start = (pageNum - 1) * pageSize
    let Count = pageSize
    emit('changePage', { Start, Count })
  },
  { deep: true }
)
const emit = defineEmits(['pageChange', 'changePage', 'objectSpanMethod', 'getSummaries', 'tableRowClassName'])
// 条数改变
const onHandleSizeChange = (val: number) => {
  state.page.pageSize = val
}
// 页数改变
const onHandleCurrentChange = (val: number) => {
  state.page.pageNum = val
}
// 表格合并单元格
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }: any) => {
  emit('objectSpanMethod', { row, column, rowIndex, columnIndex })
}
// 合并行或列的计算方法合计
const getSummaries = (param: any) => {
  emit('getSummaries', param)
  return props.tableData?.config?.summaryList
}

// table row更改颜色
const tableRowClassName = ({ row, rowIndex }: any) => {
  emit('tableRowClassName', { row, rowIndex })
}
</script>
<style>
.tableTitle {
  width: 100%;
  height: 40px;
  line-height: 40px;
  font-size: 18px;
  text-align: center;
  font-weight: bold;
  border: 1px solid rgb(235, 238, 245);
  border-bottom: none;
  color: rgb(144, 147, 153);
  margin-top: 10px;
}
.mt10{margin-top:10px;}
</style>

创建一个父组件,引入上面的table.vue组件

<template>
  <div class="my-layoutM20">
    <el-card shadow="never" :body-style="{ paddingBottom: '10px' }">
      <span class="fl" style="marginRight:10px">
        <DatePicker :datePicker="state.datePicker" @emitChange="emitChange"/>
      </span>
      <el-button size="default" type="primary" @click="onQuery()">查询 </el-button>
    </el-card>
    <Table :tableData="state.tableData"></Table>
  </div>
</template>
<script lang="ts" setup name="admin/report/tongHuaData">
// 引入组件
const Exportable = defineAsyncComponent(() => import('/@/components/exportTable/Exportable.vue'))
const Table = defineAsyncComponent(() => import('/@/components/exportTable/index.vue'))
const DatePicker = defineAsyncComponent(() => import('/@/components/search/datePicker.vue'))
const state:any = reactive({
  datePicker:[
    dayjs(new Date()).startOf('day').valueOf(),
    dayjs(new Date()).endOf('day').valueOf()
  ],
  tableData: {
    // 列表数据(必传)
    data: [],
    // 表头内容(必传,注意格式)
    header: [
      [
        { key: '', width: '', title: '起始时间', type: 'text', align: 'center' },
        { key: 'CategoryName', width: '', title: '类型', type: 'text', align: 'center' },
      ],
      [
        { key: '', width: '', title: '', type: 'text', align: 'center' },
        { key: 'StockCount', width: '', title: '库存数', type: 'text', align: 'center' },
      ],
      [
        { key: '', width: '', title: '截止时间', type: 'text', align: 'center' },
        { key: 'NoRentCount', width: '', title: '未租数', type: 'text', align: 'center' }
      ],
      [
        { key: '', width: '', title: '', type: 'text', align: 'center' },
        { key: 'RentCount', width: '', title: '已租数', type: 'text', align: 'center' }
      ],
      [
        { key: '', width: '', title: '导出时间', type: 'text', align: 'center' },
        { key: 'LossCount', width: '', title: '丢失数', type: 'text', align: 'center' }
      ],
      [
        { key: '', width: '', title: '', type: 'text', align: 'center' },
        { key: 'DamageCount', width: '', title: '损坏数', type: 'text', align: 'center' }
      ],
      [
        { key: 'ReturnTimesCount', width: '', title: '归还次数', type: 'text', align: 'center' }
      ],
      [
        { key: 'OverTimeCount', width: '', title: '超时数', type: 'text', align: 'center' }
      ],
      [
        { key: 'RentTimesCount', width: '', title: '出租次数', type: 'text', align: 'center' }
      ],
      [
        { key: 'RentRadio', width: '', title: '出租率', type: 'text', align: 'center' }
      ],
    ],
    // 配置项(必传)
    config: {
      total: null, // 列表总数
      params: {
        Count: 10, //结束页
        Start: 0, //开始页
      } as any,
      headerName:'租赁数量统计',
      fileName:useRoute().name,
      loading: false, // loading 加载
      isBorder: true, // 是否显示表格边框
      isSerialNo: true, // 是否显示表格序号
      isSelection: false, // 是否显示表格多选
      height: '98%',
      operate: {
        isOperate: false, // 是否显示表格操作栏
        width: 90,
        btns: [],
      },
    },
  },
})
// 时间日期change
const emitChange = (arr:any)=>{
  state.datePicker = arr
  state.tableData.header[1][0].title = dayjs(arr[0]).format('YYYY-MM-DD HH:mm:ss')+''
  state.tableData.header[3][0].title = dayjs(arr[1]).format('YYYY-MM-DD HH:mm:ss')+''
}
onMounted(()=>{
  state.tableData.header[1][0].title = dayjs(state.datePicker[0]).format('YYYY-MM-DD HH:mm:ss')+''
  state.tableData.header[3][0].title = dayjs(state.datePicker[1]).format('YYYY-MM-DD HH:mm:ss')+''
})
const onQuery = async () => {
  state.tableData.config.loading = true
  const option: any = {
    cmd: {
      StartTime:state.datePicker.length ? state.datePicker[0] : '',
      EndTime:state.datePicker.length ? state.datePicker[1] : ''
    }
  }
  const res = await new ReportApi().leaseNumberGetList(option).catch(() => {
    state.tableData.config.loading = false
  })
  state.tableData.data = res.Result as any
  state.tableData.config.loading = false
}
</script>

效果图
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值