当前位置:   article > 正文

Vue3表格(Table)_vue3 table

vue3 table

Vue2表格(Table)

可自定义设置以下属性:

  • 表格列的配置项(columns),类型:Array<{title?: string, width: number|string, dataIndex: string, slot?: string}>,默认 []

  • 表格数据数组(dataSource),类型:Array<any>,默认 []

  • 分页配置(pagination),类型:Pagination,默认 {}

  • 是否显示分页(showPagination),类型:boolean,默认 false

  • 数据总数(total),类型:number,默认 0

  • 是否加载中(loading),类型:boolean,默认 false

分页配置 Pagination Type:

  • 当前页码(page),类型:number

  • 每页条数(pageSize),类型:number

  • 每页可以显示多少条(pageSizeOptions),类型:string[] | number[]

  • 显示的页码数组长度(pageListNum),类型:number

  • 只有一页时是否隐藏分页(hideOnSinglePage)类型:boolean

  • 是否可以快速跳转至某页(showQuickJumper)类型:boolean

  • boolean是否展示 pageSize 切换器,当 total 大于 50 时默认为 true(showSizeChanger)类型:

  • 是否显示当前页数和数据总量(showTotal)类型:boolean

  • 分页展示位置:靠左、居中、靠右(placement)类型:'left'|'center'|'right'

效果如下图:在线预览

展示数据样式:

加载中样式:

 

无数据样式:

表格中使用到加载中(Spin)空状态(Empty)分页器(Pagination)

①创建表格组件Table.vue:

  1. <script setup lang="ts">
  2. import Spin from '../spin'
  3. import Empty from '../empty'
  4. import Pagination from '../pagination'
  5. interface Column {
  6. title?: string // 列头显示文字
  7. width: number|string // 列宽度
  8. dataIndex: string // 列数据字符索引
  9. slot?: string // 列插槽名称索引
  10. }
  11. interface Pagination { // 具体可参考 Pagination 分页组件相关 APIs
  12. page?: number // 当前页码
  13. pageSize?: number // 每页条数
  14. pageSizeOptions?: string[] | number[] // 每页可以显示多少条
  15. pageListNum?: number // 显示的页码数组长度
  16. hideOnSinglePage?: boolean // 只有一页时是否隐藏分页
  17. showQuickJumper?: boolean // 是否可以快速跳转至某页
  18. showSizeChanger?: boolean // 是否展示 pageSize 切换器,当 total 大于 50 时默认为 true
  19. showTotal?: boolean // 是否显示当前页数和数据总量
  20. placement?: 'left'|'center'|'right' // 分页展示位置:靠左、居中、靠右
  21. }
  22. interface Props {
  23. columns?: Column[] // 表格列的配置项
  24. dataSource?: any[] // 表格数据数组
  25. pagination?: Pagination // 分页配置
  26. showPagination?: boolean // 是否显示分页
  27. total?: number // 数据总数
  28. loading?: boolean // 是否加载中
  29. }
  30. withDefaults(defineProps<Props>(), {
  31. columns: () => [],
  32. dataSource: () => [],
  33. pagination: () => ({}),
  34. showPagination: true,
  35. total: 0,
  36. loading: false
  37. })
  38. const emit = defineEmits(['change'])
  39. function changePage (page: number, pageSize: number) { // 分页回调
  40. emit('change', page, pageSize)
  41. }
  42. </script>
  43. <template>
  44. <div class="m-table-wrap">
  45. <table class="m-table">
  46. <thead>
  47. <tr class="m-tr">
  48. <th class="m-th" :style="`width: ${typeof item.width === 'number' ? item.width + 'px' : item.width};`" v-for="(item, index) in columns" :key="index">
  49. {{ item.title }}
  50. </th>
  51. </tr>
  52. </thead>
  53. <tbody class="m-body">
  54. <tr class="m-tr-loading" v-show="loading">
  55. <Spin class="m-loading" size="small" :colspan="columns.length" />
  56. </tr>
  57. <tr class="m-tr-empty" v-show="!total">
  58. <td class="m-td-empty" :colspan="columns.length">
  59. <Empty class="empty" image="2" />
  60. </td>
  61. </tr>
  62. <tr class="m-tr" v-for="(data, index) in dataSource" :key="index">
  63. <td class="m-td" v-for="(col, n) in columns" :key="n" :title="data[col.dataIndex as any]">
  64. <slot v-if="col.slot" v-bind="data" :name="col.slot" :index="index">{{ data[col.dataIndex as any] || '--' }}</slot>
  65. <span v-else>{{ data[col.dataIndex as any] || '--' }}</span>
  66. </td>
  67. </tr>
  68. </tbody>
  69. </table>
  70. <Pagination
  71. class="mt20"
  72. @change="changePage"
  73. :total="total"
  74. :page="pagination.page"
  75. :pageSize="pagination.pageSize"
  76. :pageSizeOptions="pagination.pageSizeOptions"
  77. :pageListNum="pagination.pageListNum"
  78. :hideOnSinglePage="pagination.hideOnSinglePage"
  79. :showQuickJumper="pagination.showQuickJumper"
  80. :showSizeChanger="pagination.showSizeChanger"
  81. :showTotal="pagination.showTotal"
  82. :placement="pagination.placement"
  83. v-if="showPagination && total" />
  84. </div>
  85. </template>
  86. <style lang="less" scoped>
  87. .m-table-wrap {
  88. color: rgba(0, 0, 0, .65);
  89. font-size: 14px;
  90. line-height: 1.5714285714285714;
  91. border-radius: 8px 8px 0 0;
  92. .m-table {
  93. display: table;
  94. table-layout: fixed;
  95. width: 100%;
  96. text-align: left;
  97. border-radius: 8px 8px 0 0;
  98. border-collapse: separate;
  99. border-spacing: 0;
  100. margin: 0;
  101. .m-th {
  102. padding: 16px;
  103. color: rgba(0, 0, 0, .85);
  104. font-weight: 500;
  105. text-align: left;
  106. background: #fafafa;
  107. border: none;
  108. border-bottom: 1px solid #f0f0f0;;
  109. transition: background .3s ease;
  110. &:first-child {
  111. border-top-left-radius: 8px;
  112. }
  113. &:last-child {
  114. border-top-right-radius: 8px;
  115. }
  116. }
  117. .m-body {
  118. position: relative;
  119. .m-tr-loading {
  120. border: none;
  121. background-color: #FFF;
  122. .m-loading {
  123. position: absolute;
  124. width: 100%;
  125. height: 100%;
  126. }
  127. }
  128. .m-tr-empty {
  129. border: none;
  130. background-color: #FFF;
  131. &:hover {
  132. background: #FFF;
  133. }
  134. .m-td-empty {
  135. padding: 16px;
  136. border: none;
  137. border-bottom: 1px solid #f0f0f0;;
  138. .empty {
  139. margin: 32px 0;
  140. }
  141. }
  142. }
  143. }
  144. .m-tr {
  145. border: none;
  146. background-color: #FFF;
  147. transition: background-color .3s;
  148. .m-td {
  149. padding: 16px;
  150. border: none;
  151. border-bottom: 1px solid #f0f0f0;;
  152. transition: background .3s;
  153. overflow: hidden;
  154. white-space: nowrap;
  155. text-overflow: ellipsis;
  156. }
  157. &:hover {
  158. background-color: #fafafa;
  159. }
  160. }
  161. }
  162. }
  163. </style>

②在要使用的页面引入:

  1. <script setup lang="ts">
  2. import Table from './Table.vue'
  3. import { ref, reactive, onMounted } from 'vue'
  4. const loading = ref(false)
  5. const total = ref(80)
  6. const queryParams = reactive({
  7. pageSize: 10,
  8. page: 1
  9. })
  10. const columns = ref([
  11. {
  12. title: '名字',
  13. width: 100,
  14. dataIndex: 'name',
  15. slot: 'name'
  16. },
  17. {
  18. title: '年龄',
  19. width: 100,
  20. dataIndex: 'age'
  21. },
  22. {
  23. title: '职业',
  24. width: 100,
  25. dataIndex: 'job',
  26. slot: 'job'
  27. },
  28. {
  29. title: '性别',
  30. width: 100,
  31. dataIndex: 'sex'
  32. },
  33. {
  34. title: '地址',
  35. width: 120,
  36. dataIndex: 'address'
  37. }
  38. ])
  39. const tableData = ref([
  40. {
  41. name: 'Stephen',
  42. age: 30,
  43. job: 'player',
  44. sex: '男',
  45. address: 'CaliforniaCaliforniaCaliforniaCaliforniaCaliforniaCalifornia'
  46. },
  47. {
  48. name: 'Leo',
  49. age: 36,
  50. job: 'actor',
  51. sex: '男',
  52. address: 'LA'
  53. },
  54. {
  55. name: 'Mr.Dear',
  56. age: 23,
  57. job: 'boy',
  58. sex: '男',
  59. address: 'Beijing'
  60. },
  61. {
  62. name: 'superman',
  63. age: 32,
  64. job: 'boy',
  65. sex: '男',
  66. address: 'US'
  67. }
  68. ])
  69. onMounted(() => {
  70. getData()
  71. })
  72. function getData () {
  73. loading.value = true
  74. // 模拟调用接口获取列表数据
  75. setTimeout(() => {
  76. loading.value = false
  77. }, 500)
  78. }
  79. function onChange (page: number, pageSize: number) {
  80. queryParams.page = page
  81. queryParams.pageSize = pageSize
  82. getData()
  83. }
  84. </script>
  85. <template>
  86. <div>
  87. <h1>{{ $route.name }} {{ $route.meta.title }}</h1>
  88. <h2 class="mt30 mb10">基本使用</h2>
  89. <Table
  90. :columns="columns"
  91. :dataSource="tableData"
  92. :pagination="{
  93. page: 1,
  94. pageSize: 10,
  95. showQuickJumper: true,
  96. showTotal: true
  97. }"
  98. :total="total"
  99. :loading="loading"
  100. @change="onChange">
  101. <!-- 配置指定列数据 -->
  102. <template #name="record">
  103. hello {{ record.name }}
  104. </template>
  105. <template #job="{ job, index }">
  106. hi {{ job }}
  107. </template>
  108. </Table>
  109. <h2 class="mt30 mb10">加载中</h2>
  110. <Table :columns="columns" loading />
  111. <h2 class="mt30 mb10">暂无数据</h2>
  112. <Table :columns="columns" :total="0" />
  113. </div>
  114. </template>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/621634
推荐阅读
相关标签
  

闽ICP备14008679号