基于ant-table封装公共表格

这篇文章详细描述了如何在Vue项目中使用AntDesignVue库创建一个可定制的表格,包括动态列渲染、分页、行选择和排序功能。
摘要由CSDN通过智能技术生成
<template>
  <div ref="tableWrapRef" :class="props.bordered ? '' : 'border_task'">
    <ConfigProvider>
      <template #renderEmpty>
        <div class="empty">
          <a-empty :image="imgEmty"> </a-empty>
        </div>
      </template>
      <a-table
        class="ant-table-striped"
        :sticky="props.sticky"
        :dataSource="props.dataSource"
        :columns="props.columns"
        :pagination="false"
        :showSorterTooltip="false"
        :scroll="{ x: false }"
        :bordered="props.bordered"
        :expandIcon="props.expandIcon"
        :indentSize="20"
        :loading="props.loading"
        :customRow="props.customRow"
        :rowClassName="props.rowClassName ? props.rowClassName : (_, index) => (index % 2 === 1 ? 'table-striped' : null)"
        :row-key="props.rowKey || (r => r)"
        :row-selection="
          props.isCheckBox ? { selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange, getCheckboxProps: getCheckboxProps } : null
        "
        @change="sortChange"
      >
        <template #headerCell="scope">
          <template v-for="item in renderArr">
            <slot v-if="item === scope.column.headerCell" :name="item" :scope="scope" :tableWrapRef="tableWrapRef"></slot>
          </template>
          <span v-if="!renderArr.includes(scope.column.headerCell)">
            {{ scope.column.title }}
          </span>
        </template>

        <template #bodyCell="scope">
          <template v-for="item in renderArr">
            <slot v-if="item === scope.column.dataIndex" :name="item" :scope="scope" :tableWrapRef="tableWrapRef"></slot>
          </template>
          <span v-if="!renderArr.includes(scope.column.dataIndex)">
            {{ scope.record[scope.column.dataIndex] }}
          </span>
        </template>
      </a-table>
    </ConfigProvider>
  </div>

  <!-- 展示分页 -->
  <footer v-if="props.showPagination" class="flex mt-32 mb-12 page-footer">
    <span class="mr-10">{{ props.pagination.total }}</span>
    <a-pagination
      v-model:current="props.pagination.current"
      v-model:pageSize="props.pagination.pageSize"
      :show-quick-jumper="props.showQuickJumper"
      showSizeChanger
      :total="props.pagination.total"
      :page-size-options="props.pageSizeOptions"
      @change="onChange"
    />
  </footer>
</template>

<script setup>
import imgEmty from '@/assets/images/null-data.png'
import { ref, useSlots, reactive, watch } from 'vue'
import { ConfigProvider } from 'ant-design-vue'
const emits = defineEmits(['pageChange', 'sortChange', 'rowChange'])

const props = defineProps({
  // 数据源
  dataSource: {
    type: Array,
    required: true
  },
  // 数据列
  columns: {
    type: Array,
    required: true
  },
  rowKey: {
    type: String,
    default: ''
  },
  // 是否显示表格边框
  bordered: {
    type: Boolean,
    default: false
  },
  // 是否显示分页
  showPagination: {
    type: Boolean,
    default: true
  },
  // 是否展示跳页
  showQuickJumper: {
    type: Boolean,
    default: true
  },
  // 页数配置
  pageSizeOptions: {
    type: Array,
    default: ['10', '20', '30', '40', '50', '500']
  },
  // 分页
  pagination: {
    type: Object,
    default: () => {
      return {
        current: 1,
        pageSize: 10,
        total: 0
      }
    }
  },
  // 自定义展开图标
  expandIcon: {
    type: Function,
    default: null
  },
  // 加载
  loading: {
    type: Boolean,
    default: false
  },
  // 表格样式类名
  rowClassName: {
    type: Function,
    // eslint-disable-next-line
    default: function () {}
  },
  // 自定义行行为
  customRow: {
    type: Function,
    // eslint-disable-next-line
    default: function () {}
  },
  // 是否显示选择框
  isCheckBox: {
    type: Boolean,
    default: false
  },
  // 表头是否吸顶
  sticky: {
    type: Boolean,
    default: true
  },
  // 选中key
  selectedRowKeys: {
    type: Array,
    default: []
  },
  getCheckboxProps: {
    type: Function,
    default: function () {}
  }
})
const slots = useSlots()
const tableWrapRef = ref()
const renderArr = Object.keys(slots)

const state = reactive({
  selectedRowKeys: []
})
watch(
  () => props.selectedRowKeys,
  newVal => {
    state.selectedRowKeys = [...newVal]
  },
  {
    immediate: true
  }
)
// 多选
const onSelectChange = (selectedRowKeys, selectedRows) => {
  state.selectedRowKeys = selectedRowKeys
  emits('rowChange', { selectedRowKeys, selectedRows })
}

// 页码或 pageSize 改变的回调,参数是改变后的页码及每页条数
const onChange = (page, pageSize) => {
  emits('pageChange', { pageCurrent: page, pageSize })
  state.selectedRowKeys = []
}
// 表格排序
const sortChange = (pagination, filters, sorter) => {
  emits('sortChange', { pagination, filters, sorter })
}
</script>
<style lang="less" scoped>
.page-footer {
  display: flex;
  align-items: center;
  justify-content: center;
}

.empty {
  margin: 50px 0;
}

:deep(.ant-table-striped .ant-table-tbody tr.table-striped td) {
  background-color: #f2f3fc;
}
</style>

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值