Vue3表格(Table)

news2024/9/21 0:41:52

Vue2表格(Table)

可自定义设置以下属性:

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

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

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

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

  • 只有一页时是否隐藏分页器(hideOnSinglePage),类型:boolean,默认 false

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

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

效果如下图:

加载中样式:

展示数据样式:

无数据样式:

表格中使用到加载中组件(Spin)和分页组件(Pagination)

①创建表格组件Table.vue:

<script setup lang="ts">
import Spin from '../spin'
import Pagination from '../pagination'
interface Column {
  title?: string // 列头显示文字
  width?: number // 列宽度
  dataIndex?: string // 列数据字符索引
  slot?: string // 列插槽名称索引
}
defineProps({
  columns: { // 表格列的配置项
    type: Array<Column>,
    default: () => []
  },
  dataSource: { // 表格数据数组
    type: Array<any>,
    default: () => []
  },
  pagination: { // 分页器配置
    type: Object,
    default: () => {
      return {}
    }
  },
  showPagination: { // 是否显示分页器
    type: Boolean,
    default: false,
  },
  hideOnSinglePage: { // 只有一页时是否隐藏分页器
    type: Boolean,
    default: false
  },
  total: { // 数据总数
    type: Number,
    default: 0
  },
  loading: { // 页面是否加载中
    type: Boolean,
    default: false
  }
})
const emit = defineEmits(['change'])
function changePage (pager: {page: number, pageSize: number}) { // 分页器回调
  emit('change', pager)
}
</script>
<template>
  <div class="m-table-wrap">
    <table>
      <thead>
        <tr>
          <th :width="item.width" v-for="(item, index) in columns" :key="index">
            {{ item.title }}
          </th>
        </tr>
      </thead>
      <tbody class="m-body">
        <tr v-show="loading">
          <Spin class="m-loading" size="small" :colspan="columns.length" />
        </tr>
        <tr v-show="!total">
          <td class="m-empty" :colspan="columns.length">
            <svg class="u-empty-icon" viewBox="0 0 64 41" xmlns="http://www.w3.org/2000/svg">
              <g transform="translate(0 1)" fill="none" fillRule="evenodd">
                <ellipse fill="#F5F5F5" cx="32" cy="33" rx="32" ry="7"></ellipse>
                <g fillRule="nonzero" stroke="#D9D9D9">
                  <path d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"></path>
                  <path
                  d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
                  fill="#FAFAFA"
                  ></path>
                </g>
              </g>
            </svg>
            <p class="u-empty-desc">暂无数据</p>
          </td>
        </tr>
        <tr v-for="(data, index) in dataSource" :key="index">
          <td v-for="(col, ind) in columns" :key="ind" :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"
      :current="pagination.page"
      :pageSize="pagination.pageSize"
      :total="total"
      :hideOnSinglePage="hideOnSinglePage"
      :showQuickJumper="true"
      :showTotal="true"
      placement="right"
      v-if="showPagination && total" />
  </div>
</template>
<style lang="less" scoped>
.m-table-wrap {
  color: rgba(0, 0, 0, 0.65);
  font-size: 14px;
  line-height: 1.5;
  table {
    table-layout: fixed;
    width: 100%;
    text-align: left;
    border-radius: 4px 4px 0 0;
    border-collapse: separate;
    border-spacing: 0;
    thead tr th {
      padding: 16px;
      color: rgba(0, 0, 0, 0.85);
      font-weight: 500;
      text-align: left;
      background: #fafafa;
      border-bottom: 1px solid #e8e8e8;
      transition: background .3s ease;
      &:first-child {
        border-top-left-radius: 4px;
      }
      &:last-child {
        border-top-right-radius: 4px;
      }
    }
    .m-body {
      position: relative;
      .m-loading {
        position: absolute;
        width: 100%;
        height: 100%;
      }
      .m-empty {
        padding: 48px 16px;
        color: rgba(0, 0, 0, 0.25);
        font-size: 14px;
        text-align: center;
        background: #fff;
        border-bottom: 1px solid #e8e8e8;
        border-radius: 0 0 2px 2px;
        .u-empty-icon {
          width: 64px;
          height: 41px;
          margin-bottom: 8px;
        }
        .u-empty-desc {
          color: rgba(0, 0, 0, 0.25);
          font-size: 14px;
        }
      }
    }
    tbody tr {
      transition: background .3s;
      td {
        padding: 16px;
        border-bottom: 1px solid #e8e8e8;
        transition: background .3s;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
      &:hover {
        background: saturate(fade(@themeColor, 12%), 30%);
        
      }
    }
  }
}
</style>

②在要使用的页面引入:

<script setup lang="ts">
import Table from './Table.vue'
import { ref } from 'vue'
const loading = ref(false)
const total = ref(35)
const queryParams = ref({
        pageSize: 5,
        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'
        }
      ])
function getData () {
  loading.value = true
  // 调用分页接口获取列表数据
}
function onChangeTable (pagination: {page: number, pageSize: number}) {
  console.log('pagination:', pagination)
  queryParams.value.page = pagination.page
  queryParams.value.pageSize = pagination.pageSize
  getData()
}
</script>
<template>
  <div>
    <h2 class="mb10">Table 表格基本使用</h2>
    <Table
      :columns="columns"
      :dataSource="tableData"
      :pagination="{
        page: queryParams.page,
        pageSize: queryParams.pageSize
      }"
      :showPagination="true"
      :hideOnSinglePage="false"
      :total="total"
      :loading="loading"
      @change="onChangeTable">
    <!-- 配置指定列数据 -->
    <template #name="record">
        hello {{ record.name }}
      </template>
      <template #job="{ job, index }">
        hi {{ job }}
      </template>
    </Table>
    <h2 class="mt30 mb10">加载中表格 (loading: true)</h2>
    <Table
      :columns="columns"
      :dataSource="[]"
      :pagination="{
        page: queryParams.page,
        pageSize: queryParams.pageSize
      }"
      :showPagination="true"
      :hideOnSinglePage="false"
      :total="0"
      :loading="true"
      @change="onChangeTable"
    ></Table>
    <h2 class="mt30 mb10">无数据表格 (total: 0)</h2>
    <Table
      :columns="columns"
      :dataSource="[]"
      :pagination="{
        page: queryParams.page,
        pageSize: queryParams.pageSize
      }"
      :showPagination="true"
      :hideOnSinglePage="false"
      :total="0"
      :loading="false"
      @change="onChangeTable"
    ></Table>
  </div>
</template>
<style lang="less" scoped>
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/440976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

史上最全面的苹果公司PMO的运作模式详解

01 苹果公司PMO的发展历程 1. 初期阶段&#xff1a; 在苹果公司刚创立的早期&#xff0c;没有明确的PMO组织。项目经理直接向CEO Steve Jobs汇报&#xff0c;项目管理在公司内部较为分散。 2. 1997年-2001年&#xff1a; 在这段时间内&#xff0c;苹果公司开始成立项目管理…

PasteSpider之关于字符串模板占位字符等的说明

PasteSpider中&#xff0c;构建&#xff0c;部署等都是通过命令执行的&#xff0c;为了更加的灵活&#xff0c;引入了不同的变量&#xff0c;以便适合不同的需求使用。 命令占位符 注&#xff01;&#xff01;&#xff01;&#xff0c;占位符的格式为{{对象.属性}},他们之间没有…

【LeetCode: 1691. 堆叠长方体的最大高度 | 暴力递归=>记忆化搜索=>动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

vue2+vue3——42+

vue2vue3——42 vue2 v-cloak指令【14:14】调网速 &#xff1a; no throttling 不让慢 &#xff1b; offline 断网JS 阻塞红色 外部JS &#xff1b; 绿色 网页核心 &#xff1b; 粉色 JS 脚本红色 外部JS 我要走不了&#xff0c; 谁都别想走 &#xff1a; 绿色 不可以渲染到页面…

【安全与风险】互联网协议漏洞

互联网协议漏洞 互联网基础设施TCP协议栈因特网协议&#xff08;IP&#xff09;IP路由IP协议功能(概述)问题:没有src IP认证用户数据报协议&#xff08;UDP&#xff09;传输控制协议 (TCP)TCP报头TCP(三向)握手基本安全问题数据包嗅听TCP连接欺骗随机初始TCP SNs 路由的漏洞Arp…

【OJ比赛日历】快周末了,不来一场比赛吗? #04.15-04.21 #17场

CompHub 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号同时会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 更多比赛信息见 CompHub主页 或 点击文末阅读原文 以下信息仅供参考&#xff0c;以比赛官网为准 目录 2023-04-15&…

openpnp - 顶部相机辅助光的选择

文章目录 openpnp - 顶部相机辅助光的选择概述折腾的过程简易灯板市售的环形灯(不带漫射板)市售的环形灯(不带漫射板) LED单色光调光控制器.市售的环形灯(带漫射板)市售的环形灯(带漫射板) 自己拆解(降低LED灯路数)END openpnp - 顶部相机辅助光的选择 概述 终于将顶部相机…

Debain初始化配置(一)

目录 1.前言 2.简介 3.Debian11 软件包安装与配置 介绍 3.1.Debian 软件包工具 4.Debian11 软件包安装 4.1、更新索引 4.2.软件包升级 4.3.软件包安装 4.4.软件包删除 4.5.软件包清理 5.Debian11 软件包配置 6.Debian11 系统环境初始化 6.1.系统升级 6.2.安装 S…

哈希表——我欲修仙(功法篇)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️我欲修仙】 学习名言&#xff1a;莫等闲、白了少年头&#xff0c;空悲切。——岳飞 系列文章目录 第一章 ❤️ 学习前的必知知识 第二章 ❤️ 二分查找 文章目录 系列文章目录什么是哈希表&#xff…

【AIGC】Stable Diffusion原理快速上手,模型结构、关键组件、训练预测方式

【AIGC】Stable Diffusion的建模思想、训练预测方式快速 在这篇博客中&#xff0c;将会用机器学习入门级描述&#xff0c;来介绍Stable Diffusion的关键原理。目前&#xff0c;网络上的使用教程非常多&#xff0c;本篇中不会介绍如何部署、使用或者微调SD模型。也会尽量精简语…

靶机精讲之Tr0ll

主机发现 nmap扫描 端口扫描 UDP扫描 服务扫描 先从ftp和http下手&#xff0c;shh排后 尝试ftp 匿名登录 查看文件下载的信息 wireshark利用读取文件 strings读取 lol.pcap文本 读代码感觉像目录 进行访问 下载 拷贝到目录下&#xff08;记得背后加点&#xff09; file查看文…

Redis五大数据类型

关于Redis的五大数据类型&#xff0c;它们分别为&#xff1a;String、List、Hash、Set、SortSet。本文将会从它的底层数据结构、常用操作命令、一些特点和实际应用这几个方面进行解析。对于数据结构的解析&#xff0c;本文只会从大的方面来解析&#xff0c;不会介绍详细的代码实…

Linux_Shell命令解析

简介 在linux终端中执行ls命令&#xff0c;ls命令是如何被解析并且执行的。Shell命令的格式一般为&#xff1a; [commond] [-options] [parameter]执行命令 命令的选项 命令的参数当执行ls命令是显示当前目录下所有文件的名称 执行ls -l命令是显示当前目录下所有文件的属性…

软件工程开发文档写作教程(01)—开发文档的意义与作用

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文参考资料&#xff1a;电子工业出版社《软件文档写作教程》 马平&#xff0c;黄冬梅编著 软件工程开发文档的意义 软件文档是整个软件开发工作的基础&#xff0c;现代工程…

Maven(一)基础入门

目录 一、Maven简介1.背景2.Maven是什么3.Maven的作用 二、下载与安装1.下载2.安装3.配置环境变量 三、Maven基础概念1.仓库2.坐标3.本地仓库配置4.远程仓库配置5.阿里云-镜像仓库配置6.全局 settings 与用户 settings 区别 四、第一个Maven项目&#xff08;手工制作&#xff0…

【Python】快速简单搭建HTTP服务器并公网访问「cpolar内网穿透」

转载自远程内网穿透的文章&#xff1a;【Python】快速简单搭建HTTP服务器并公网访问「cpolar内网穿透」 1.前言 Python作为热度比较高的编程语言&#xff0c;其语法简单且语句清晰&#xff0c;而且python有良好的兼容性&#xff0c;可以轻松的和其他编程语言&#xff08;(比如…

Qt/QML编程学习之心得:ALSA音频开发(六)

Linux内核中对音频播放和捕获的最初支持是由开放声音系统(OSS)提供的。OSS API是为音频而设计的带有16位双通道回放和捕获的卡,以及随后的API通过open()、close()、read()和write()系统调用的标准POSIX。OSS的主要问题是,虽然基于文件的API实际上易于应用程序开发人…

电磁阀“位”与“通”的详细解说(示意图)

电磁阀是用电磁控制的工业设备&#xff0c;是用来控制流体的自动化基础元件&#xff0c;属于执行器。 而气动电磁阀是其中的一种&#xff0c;是通过控制阀体的移动来档住或漏出不同的排油的孔&#xff0c;而进油孔是常开的&#xff0c;液压油就会进入不同的排油管&#xff0c;…

物联网定位技术|实验报告|实验一 Wi-Fi指纹定位

目录 实验1 Wi-Fi指纹定位 1. 实验目标 2. 实验背景 3. 实验原理 3.1 WIFI基础知识 3.2室内定位方法建模 3.3指纹定位算法 ①离线/训练阶段 ②在线/定位阶段 4. 关键代码 5. 实验结果 6. 室内定位误差分析 6.1 非视距传播 6.2 多径传播 6.3 阴影效应 7. 实验总结 物联网定位技…

ESP32学习三-环境搭建(ESP-IDF V5.0,Ubuntu20.4)

一、准备事项 Ubuntu 20.04。具体安装可以参考如下链接。使用VMware安装Ubuntu虚拟机和VMware Tools_t_guest的博客-CSDN博客 二、安装ESP-IDF 1&#xff09;、确认python3版本 输入python3 --version来确认python3的版本。因为要安装ESP-IDF 5.0版本&#xff0c;python3的版本…