赞
踩
可自定义设置以下属性:
表格列的配置项(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:
- <script setup lang="ts">
- import Spin from '../spin'
- import Empty from '../empty'
- import Pagination from '../pagination'
- interface Column {
- title?: string // 列头显示文字
- width: number|string // 列宽度
- dataIndex: string // 列数据字符索引
- slot?: string // 列插槽名称索引
- }
- interface Pagination { // 具体可参考 Pagination 分页组件相关 APIs
- page?: number // 当前页码
- pageSize?: number // 每页条数
- pageSizeOptions?: string[] | number[] // 每页可以显示多少条
- pageListNum?: number // 显示的页码数组长度
- hideOnSinglePage?: boolean // 只有一页时是否隐藏分页
- showQuickJumper?: boolean // 是否可以快速跳转至某页
- showSizeChanger?: boolean // 是否展示 pageSize 切换器,当 total 大于 50 时默认为 true
- showTotal?: boolean // 是否显示当前页数和数据总量
- placement?: 'left'|'center'|'right' // 分页展示位置:靠左、居中、靠右
- }
- interface Props {
- columns?: Column[] // 表格列的配置项
- dataSource?: any[] // 表格数据数组
- pagination?: Pagination // 分页配置
- showPagination?: boolean // 是否显示分页
- total?: number // 数据总数
- loading?: boolean // 是否加载中
- }
- withDefaults(defineProps<Props>(), {
- columns: () => [],
- dataSource: () => [],
- pagination: () => ({}),
- showPagination: true,
- total: 0,
- loading: false
- })
- const emit = defineEmits(['change'])
- function changePage (page: number, pageSize: number) { // 分页回调
- emit('change', page, pageSize)
- }
- </script>
- <template>
- <div class="m-table-wrap">
- <table class="m-table">
- <thead>
- <tr class="m-tr">
- <th class="m-th" :style="`width: ${typeof item.width === 'number' ? item.width + 'px' : item.width};`" v-for="(item, index) in columns" :key="index">
- {{ item.title }}
- </th>
- </tr>
- </thead>
- <tbody class="m-body">
- <tr class="m-tr-loading" v-show="loading">
- <Spin class="m-loading" size="small" :colspan="columns.length" />
- </tr>
- <tr class="m-tr-empty" v-show="!total">
- <td class="m-td-empty" :colspan="columns.length">
- <Empty class="empty" image="2" />
- </td>
- </tr>
- <tr class="m-tr" v-for="(data, index) in dataSource" :key="index">
- <td class="m-td" v-for="(col, n) in columns" :key="n" :title="data[col.dataIndex as any]">
- <slot v-if="col.slot" v-bind="data" :name="col.slot" :index="index">{{ data[col.dataIndex as any] || '--' }}</slot>
- <span v-else>{{ data[col.dataIndex as any] || '--' }}</span>
- </td>
- </tr>
- </tbody>
- </table>
- <Pagination
- class="mt20"
- @change="changePage"
- :total="total"
- :page="pagination.page"
- :pageSize="pagination.pageSize"
- :pageSizeOptions="pagination.pageSizeOptions"
- :pageListNum="pagination.pageListNum"
- :hideOnSinglePage="pagination.hideOnSinglePage"
- :showQuickJumper="pagination.showQuickJumper"
- :showSizeChanger="pagination.showSizeChanger"
- :showTotal="pagination.showTotal"
- :placement="pagination.placement"
- v-if="showPagination && total" />
- </div>
- </template>
- <style lang="less" scoped>
- .m-table-wrap {
- color: rgba(0, 0, 0, .65);
- font-size: 14px;
- line-height: 1.5714285714285714;
- border-radius: 8px 8px 0 0;
- .m-table {
- display: table;
- table-layout: fixed;
- width: 100%;
- text-align: left;
- border-radius: 8px 8px 0 0;
- border-collapse: separate;
- border-spacing: 0;
- margin: 0;
- .m-th {
- padding: 16px;
- color: rgba(0, 0, 0, .85);
- font-weight: 500;
- text-align: left;
- background: #fafafa;
- border: none;
- border-bottom: 1px solid #f0f0f0;;
- transition: background .3s ease;
- &:first-child {
- border-top-left-radius: 8px;
- }
- &:last-child {
- border-top-right-radius: 8px;
- }
- }
- .m-body {
- position: relative;
- .m-tr-loading {
- border: none;
- background-color: #FFF;
- .m-loading {
- position: absolute;
- width: 100%;
- height: 100%;
- }
- }
- .m-tr-empty {
- border: none;
- background-color: #FFF;
- &:hover {
- background: #FFF;
- }
- .m-td-empty {
- padding: 16px;
- border: none;
- border-bottom: 1px solid #f0f0f0;;
- .empty {
- margin: 32px 0;
- }
- }
- }
- }
- .m-tr {
- border: none;
- background-color: #FFF;
- transition: background-color .3s;
- .m-td {
- padding: 16px;
- border: none;
- border-bottom: 1px solid #f0f0f0;;
- transition: background .3s;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
- &:hover {
- background-color: #fafafa;
- }
- }
- }
- }
- </style>
②在要使用的页面引入:
- <script setup lang="ts">
- import Table from './Table.vue'
- import { ref, reactive, onMounted } from 'vue'
- const loading = ref(false)
- const total = ref(80)
- const queryParams = reactive({
- pageSize: 10,
- page: 1
- })
- const columns = ref([
- {
- title: '名字',
- width: 100,
- dataIndex: 'name',
- slot: 'name'
- },
- {
- title: '年龄',
- width: 100,
- dataIndex: 'age'
- },
- {
- title: '职业',
- width: 100,
- dataIndex: 'job',
- slot: 'job'
- },
- {
- title: '性别',
- width: 100,
- dataIndex: 'sex'
- },
- {
- title: '地址',
- width: 120,
- dataIndex: 'address'
- }
- ])
- const tableData = ref([
- {
- name: 'Stephen',
- age: 30,
- job: 'player',
- sex: '男',
- address: 'CaliforniaCaliforniaCaliforniaCaliforniaCaliforniaCalifornia'
- },
- {
- name: 'Leo',
- age: 36,
- job: 'actor',
- sex: '男',
- address: 'LA'
- },
- {
- name: 'Mr.Dear',
- age: 23,
- job: 'boy',
- sex: '男',
- address: 'Beijing'
- },
- {
- name: 'superman',
- age: 32,
- job: 'boy',
- sex: '男',
- address: 'US'
- }
- ])
- onMounted(() => {
- getData()
- })
- function getData () {
- loading.value = true
- // 模拟调用接口获取列表数据
- setTimeout(() => {
- loading.value = false
- }, 500)
- }
- function onChange (page: number, pageSize: number) {
- queryParams.page = page
- queryParams.pageSize = pageSize
- getData()
- }
- </script>
- <template>
- <div>
- <h1>{{ $route.name }} {{ $route.meta.title }}</h1>
- <h2 class="mt30 mb10">基本使用</h2>
- <Table
- :columns="columns"
- :dataSource="tableData"
- :pagination="{
- page: 1,
- pageSize: 10,
- showQuickJumper: true,
- showTotal: true
- }"
- :total="total"
- :loading="loading"
- @change="onChange">
- <!-- 配置指定列数据 -->
- <template #name="record">
- hello {{ record.name }}
- </template>
- <template #job="{ job, index }">
- hi {{ job }}
- </template>
- </Table>
- <h2 class="mt30 mb10">加载中</h2>
- <Table :columns="columns" loading />
- <h2 class="mt30 mb10">暂无数据</h2>
- <Table :columns="columns" :total="0" />
- </div>
- </template>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。