在vue3中,用jsx模板封装ant-design-vue2和3的table组件

813 阅读1分钟

注:ant-design-vue2和3版本的table组件中对slots的用法不同,下面细说。

一、ant-design-vue的table组件封装

jsx

import { defineComponent } from "vue"
import { ConfigProvider, Spin, Table } from 'ant-design-vue'
import zhCN from 'ant-design-vue/es/locale/zh_CN';
export default defineComponent({
  name: 'btTable',
  props: {
    rowSelection: Object,
    dataSource: Array,
    columns: Array,
    nullData: {
      type: String,
      default: '暂无数据',
    },
    pagination: Object,
    loading: Boolean,
    tips: {
      type: String,
      default: '加载中...',
    },
    isPage: {
      type: Boolean,
      default: true
    },
    isBroder: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: 'middle'
    },
    styles: {
      type: Object,
      default: () => {
        return {
          marginTop: ''
        }
      }
    }
  },
  setup(props, {slots, attrs}) {
    const tableProps = () => {
      const {isPage, pagination, isBroder} = props
      return {
        ...attrs,
        ...props,
        ...{
          pagination: isPage ? {
            ...pagination,
            showSizeChanger: true,
            showTotal: total => `共${total}条`,
            pageSizeOptions: ['15', '30', '50', '100']
          } : false,
          rowKey: (record, index) => {
            return record?.key || index
          },
          bordered: isBroder
        }
      }
    }
    const tableFunc = () => (
      <ConfigProvider locale={zhCN}>
        <Table
          v-slots={slots}
          {...tableProps()}
        />
      </ConfigProvider>
    )
    const btTable = () => {
      const {loading, tips, styles, dataSource} = props;
      return (
        <Spin
          spinning={loading}
          tip={tips}
          style={styles}
        >
          {dataSource.length && tableFunc()}
        </Spin>
      )
    }
    return () => (
      <div style="position: relative">
        {btTable()}
      </div>
    )
  }
})

ant-design-vue2用法

<TableInfo 
    :rowSelection="tableRowSelection()"
    :columns="state.columns"
    :dataSource="state.tableData"
    :pagination="state.pagination"
>
    <template #tags="{ record }">
      <Tag
        v-for="item in record.tags"
        :key="item"
        :color="item === 'loser' ? 'volcano' : item.length > 5 ? 'geekblue' : 'green'"
      >
        <span>{{ item.toUpperCase() }}</span>
      </Tag>
    </template>
    <template #action="{ record }">
      <span>
        <a>{{ record.name }}</a>
        <Divider type="vertical" />
        <a>删除</a>
        <Divider type="vertical" />
        <a class="ant-dropdown-link">
          更多功能
          <down-outlined />
        </a>
      </span>
    </template>
</TableInfo>

columns中需要写slots参数:

//这是2版本的写法
{
      title: "操作",
      key: "action",
      slots: {
        customRender: "action",// slots需要用customRender才生效
      },
},

ant-design-vue3用法

3版本写法:在使用的时候直接判断key

//这是3版本的写法
<btTable>
<template #headerCell="{ column }">
      <template v-if="column.key === 'name'">
        <span>
          <smile-outlined />
          Name
        </span>
      </template>
</template>
<template #bodyCell="{ column, record }">
      <template v-if="column.key === 'name'">
        <a>
          {{ record.name }}
        </a>
      </template>
      <template v-else-if="column.key === 'tags'">
        <span>
          <a-tag
            v-for="tag in record.tags"
            :key="tag"
            :color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
          >
            {{ tag.toUpperCase() }}
          </a-tag>
        </span>
      </template>
      <template v-else-if="column.key === 'action'">
        <span>
          <a>Invite 一 {{ record.name }}</a>
          <a-divider type="vertical" />
          <a>Delete</a>
          <a-divider type="vertical" />
          <a class="ant-dropdown-link">
            More actions
            <down-outlined />
          </a>
        </span>
      </template>
</template>
</btTable>