vue3 组件-表格分页 
该组件依赖element-plus。
进度 
- typescript 类型提示(属性、方法、el-table 与 el-pagination 自带 ts 类型)
- json 配置 el-table
- 控制栏自定义
- 单元格编辑
- 编辑行
- 自动请求接口
- 接口请求参数与响应数据路径自定义
- 接口请求参数序列化
- v-loading 显示及超时提示文字
- 空状态提示文字及超时提示文字
-  导出为xlsx
按需引入 
ts
import { KTable } from "@tomiaa/vue3-components"基础用法 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
  />
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "地址",
    prop: "address",
  },
]
</script>控制栏 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
    @edit="edit"
    @delete="delRow"
  />
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "控制",
    action: true,
  },
]
// 点击编辑按钮
const edit = (scope: any) => {
  console.log(scope)
}
// 点击删除按钮
const delRow = (scope: any) => {
  console.log(scope)
}
</script>函数自定义控制栏 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
    @edit="edit"
    @delete="delRow"
  />
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "控制",
    width: 300,
    action: true, // 表示为控制列
    actionConfig: {
      // 控制列的配置
      showEdit: true, // 显示编辑按钮
      showDelete: true, // 显示删除按钮
      editText: "详情",
      deleteText: "撤回",
      custom(list, scope) {
        // 自定义方法
        list[0].icon = "ElIconInfoFilled"
        list.push({
          el: "el-button",
          size: "small",
          children: "自定义按钮",
          icon: "ElIconEdit",
          onClick() {
            console.log(scope)
          },
        })
        return list
      },
    },
  },
]
// 点击编辑按钮
const edit = (scope: any) => {
  console.log(scope)
}
// 点击删除按钮
const delRow = (scope: any) => {
  console.log(scope)
}
</script>插槽 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
  >
    <template #control>
      <el-button>插槽按钮</el-button>
    </template>
  </KTable>
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "控制",
    slot: "control", // 插槽名称
  },
]
</script>单元格内编辑 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
  >
  </KTable>
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "可编辑",
    prop: "address",
    editable: true, // 可编辑
  },
]
</script>函数自定义单元格编辑按钮 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
    @confirm-edit-cell="confirmEditCell"
    @cancel-edit-cell="cancelEditCell"
  >
  </KTable>
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "可编辑",
    prop: "address",
    editable: true, // 可编辑
    editableConfig: {
      // 单元格内编辑配置
      showClose: true, // 显示编辑时取消按钮
      showEnter: true, // 显示编辑时确认按钮
      custom(list, scope, isEdit) {
        list.push({
          el: "el-button",
          size: "small",
          icon: "ElIconCheck",
          onClick() {
            console.log(scope)
            isEdit.value = false // 关闭编辑状态
          },
        })
        return list
      },
    },
  },
]
// 确定编辑
const confirmEditCell = (scope: any) => {
  console.log(scope)
}
// 取消编辑
const cancelEditCell = (scope: any) => {
  console.log(scope)
}
</script>插槽自定义单元格编辑按钮 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
  >
    <!-- 编辑时按钮插槽 -->
    <template #editControlIcon="scope">
      <el-button
        style="margin-left: 0.2em"
        size="small"
        @click="enter(scope)"
        >确认</el-button
      >
    </template>
    <!-- 未编辑时按钮插槽 -->
    <template #editIcon="scope">
      <el-button
        style="margin-left: 0.2em"
        size="small"
        @click="editCell(scope)"
        >编辑</el-button
      >
    </template>
  </KTable>
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "可编辑",
    prop: "address",
    width: 300,
    editable: true, // 可编辑
  },
]
// 编辑
const editCell = ({ isEdit, row }: any) => {
  console.log(row, "dasdas")
  isEdit.value = true
}
// 确定编辑
const enter = ({ isEdit, row }: any) => {
  console.log(row)
  isEdit.value = false // 取消编辑状态
}
</script>分页 
查看代码
vue
<template>
  <KTable
    show-pagination
    :current-page="pagination.currentPage"
    :total="pagination.total"
    :data="tableData"
    :options="options"
    layout="total, prev, pager, next"
    background
    @update:current-page="handleCurrentChange"
  >
  </KTable>
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
]
const pagination = ref({
  total: 300,
  currentPage: 2,
})
const handleCurrentChange = (num: number) => {
  pagination.value.currentPage = num
  console.log(num, "temp8")
}
</script>自动调用接口 
基础用法 
打开控制台查看网络请求
查看代码
vue
<template>
  <KTable
    :options="options"
    get-url="/getList"
    :get-config="{
      method: 'post',
    }"
    with-page-path="pages"
    :with-query="{
      name: '这是携带的查询参数',
    }"
    with-query-path="query"
    data-path="data.result"
    total-path="data.pagination.total"
    show-pagination
    :total="300"
  >
  </KTable>
</template>
<script setup lang="ts">
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
]
</script>完整示例 
查看代码
vue
<template>
  <KTable
    ref="kTable"
    :options="options"
    show-pagination
    :server="myAxios"
    get-url="/getData"
    :get-config="{
      method: 'post',
    }"
    with-page="data"
    with-page-path="pagination"
    :replace-fields="{
      currentPage: 'current',
      pageSize: 'size',
    }"
    :with-query="{
      name: '这里是查询参数',
    }"
    with-query-path="query"
    stringify
    data-path="data.result"
    total-path="data.total"
    show-load-in-get
    element-loading-text="正在加载中"
    :el-loading-text-timeout="3000"
    el-loading-text-timeout-text="加载较慢,请耐心等待"
    empty-tip="正在加载数据中..."
    :empty-tip-timeout="3000"
    empty-tip-timeout-text="数据加载较慢,马上就来..."
    @before-get-data="beforeGetData"
    @after-get-data="afterGetData"
    @fail-to-get-data="failToGetData"
  >
  </KTable>
</template>
<script setup lang="ts">
import type { TableProps } from "@tomiaa/vue3-components"
import { ref, onMounted } from "vue"
import { KTable } from "@tomiaa/vue3-components"
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
]
// 模拟 axios 请求
const myAxios: any = (req: any) =>
  new Promise(res => {
    console.log(req, "请求的参数")
    setTimeout(() => {
      res({
        code: 200,
        data: {
          result: [
            {
              date: "2016-05-03",
              name: "Tom",
              address: "No. 189, Grove St, Los Angeles",
            },
            {
              date: "2016-05-01",
              name: "Tom",
              address: "No. 189, Grove St, Los Angeles",
            },
          ],
          total: 390,
        },
        msg: "成功",
      })
    }, 10000)
  })
const beforeGetData = (getConfig: any) => {
  console.log("请求接口之前,axios的参数", getConfig)
}
const afterGetData = (response: any) => {
  console.log("接口请求成功", response)
}
const failToGetData = (error: any) => {
  console.log("接口请求失败", error)
}
const kTable = ref()
onMounted(() => {
  // 手动请求数据
  // kTable.value.getData()
})
</script>编辑行 
查看代码
vue
<template>
  <KTable
    :data="tableData"
    :options="options"
    edit-row
    @confirm-edit-row="confirmEditRow"
    @cancel-edit-row="cancelEditRow"
  >
  </KTable>
</template>
<script setup lang="ts">
import { ref } from "vue"
import type { TableProps } from "@tomiaa/vue3-components"
import { KTable } from "@tomiaa/vue3-components"
const tableData = ref<any>([
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
])
const options: TableProps["options"] = [
  {
    label: "名称",
    prop: "name",
  },
  {
    label: "时间",
    prop: "date",
  },
  {
    label: "编辑行",
    action: true,
  },
]
const confirmEditRow = (scope: any) => {
  console.log(scope, "确定编辑行")
}
const cancelEditRow = (scope: any) => {
  console.log(scope, "取消编辑行")
}
</script>属性 
| 属性 | 说明 | 类型 | 默认值 | 
|---|---|---|---|
| options | 表格配置 | array(点我查看) | |
| editRow | 点击编辑时是否为编辑行 | boolean | false | 
| showPagination | 是否显示分页 | boolean | false | 
| server | 发送请求的 axios 实例 | AxiosStatic | axios | 
| getUrl | 获取分页的请求地址 | string | |
| withPage | 获取分页时传入分页对象(pageSize,currentPage)在 axios 中的哪个字段,默认 get请求为params,post请求为data。false为不携带分页参数 | string|boolean | |
| withPagePath | 获取分页时加入的分页对象参数在 axios 的哪个对象路径下,默认在提交的发送的最外层,不建议在 get请求中使用,post请求时如填写pages即提交时的参数为{data: {pages: { currentPage: 1, pageSize: 10 }}} | string | |
| withQuery | 请求时的查询参数 | object | |
| withQueryPath | 获取分页时查询参数在 axios 的哪个对象路径下 | string | |
| stringify | 发送请求是携带的参数序列化,withPage 为 "data" 时生效,只会在请求体中序列化,且 Content-Type会被默认设置为application/x-www-form-urlencoded | boolean | false | 
| getConfig | 请求分页的配置,为 axios 提交的参数 | AxiosRequestConfig | {method: "get"} | 
| replaceFields | 要替换请求时分页参数的字段 | { pageSize?: string; currentPage?: string } | { pageSize: "pageSize", currentPage: "currentPage" } | 
| dataPath | 获取数据之后 data 数据的路径 | string | data.data | 
| totalPath | 获取数据之后总条数的路径 | string | data.total | 
| showLoadInGet | 自动获取数据时,在表格上显示 element 的 v-loading | boolean | true | 
| elementLoadingText | 显示在 v-loading 加载图标下方的加载文案 | string | 正在加载中... | 
| elLoadingTextTimeout | 超过多少毫秒后更换 v-loading 的 提示文字 | number | 8000 | 
| elLoadingTextTimeoutText | 超过 EmptyTipTimeout 毫秒后更换 v-loading 的 提示文字 | string | 数据加载较慢,请耐心等待... | 
| emptyTip | 在自动获取数据时替换 empty插槽,table 中显示提示的文字,为假值时则不显示 | string | 正在加载中... | 
| emptyTipTimeout | 超过多少毫秒后更换提示文字 | number | 8000 | 
| emptyTipTimeoutText | 超过 EmptyTipTimeout毫秒后更换的提示文字 | string | 数据加载较慢,请耐心等待... | 
| actionConfig | 全局的控制栏配置 | ActionConfig | |
| actionConfig.editText | 编辑的文字 | string | 编辑 | 
| actionConfig.deleteText | 删除的文字 | string | 删除 | 
| actionConfig.showEdit | 显示编辑/确认 | boolean | true | 
| actionConfig.showDelete | 显示删除/取消 | boolean | true | 
| editRowEnterText | 编辑行时确认文字 | string | 确定 | 
| editRowCloseText | 编辑行是取消文字 | string | 确定 | 
| actionConfig.custom | 函数自定义操作栏 | function | |
| ...rest | 剩余属性,为 el-table属性与el-pagination属性 | 
options-配置 
这是options表格的每一列el-column配置,全部为非必填
| 属性 | 说明 | 类型 | 默认值 | 
|---|---|---|---|
| slot | 插槽名 | string | |
| action | 是否为操作栏 | string | false | 
| actionConfig | 操作栏配置,该值存在即视为 action 为 true | object | |
| actionConfig.editText | 编辑的文字 | string | 编辑 | 
| actionConfig.deleteText | 删除的文字 | string | 删除 | 
| actionConfig.showEdit | 显示编辑/确认 | boolean | true | 
| actionConfig.showDelete | 显示删除/取消 | boolean | true | 
| editRowEnterText | 编辑行时确认文字 | string | 确定 | 
| editRowCloseText | 编辑行是取消文字 | string | 确定 | 
| actionConfig.custom | 函数自定义操作栏 | function | |
| editable | 单元格开启编辑 | boolean | false | 
| editableConfig | 单元格编辑配置,该值存在即视为 editable 为 true | object | |
| editableConfig.showEnter | 显示编辑中的确认按钮 | boolean | true | 
| editableConfig.showClose | 显示编辑中的取消按钮 | boolean | true | 
| editableConfig.custom | 函数自定义单元格编辑 | function | |
| ...rest | 剩余属性为 el-table-column 的属性 | 
事件 
| 事件名 | 说明 | 回调参数 | 
|---|---|---|
| edit | 操作栏点击编辑 | scope | 
| delete | 操作栏点击删除 | scope | 
| confirmEditCell | 单元格内确定编辑 | scope | 
| cancelEditCell | 单元格内取消编辑 | scope | 
| confirmEditRow | 编辑行确定 | scope | 
| cancelEditRow | 编辑行取消 | scope | 
| beforeGetData | 自动请求分页之前 | getConfig | 
| afterGetData | 自动请求分页成功后 | AxiosResponse | 
| failToGetData | 自动请求分页失败 | AxiosResponse | 
插槽 
| 插槽名 | 说明 | 作用域 | 
|---|---|---|
| append | el-table 自带插槽,插入至表格最后一行之后的内容, 如果需要对表格的内容进行无限滚动操作,可能需要用到这个 slot。 若表格有合计行,该 slot 会位于合计行之上。 | |
| empty | el-table 自带插槽,当数据为空时自定义的内容 | |
| header | Table-column 自带插槽,自定义表头的内容 | { column, $index } | 
| editIcon | 单元格编辑按钮插槽 | {...scope,isEdit: Ref<boolean>} | 
| editControlIcon | 编辑确认取消按钮插槽 | {...scope,isEdit: Ref<boolean>} | 
方法 
| 方法名 | 说明 | 参数 | 
|---|---|---|
| elPagination | el-pagination 的属性和方法 | |
| elTable | elTable 的属性和方法 | |
| getData | 请求数据 |