Vue2表格(Table)

简介: 这是一个基于 Vue3 的表格组件,提供了灵活的数据展示与分页功能。主要接收表格列配置 `columns`、数据源 `dataSource`、分页器配置 `pagination` 等参数,并支持加载状态显示及单页隐藏分页器等特性。组件内置了加载中组件 `Spin` 和分页组件 `Pagination`,样式参考 ant-design。使用时需在目标页面引入组件并设置相关属性即可实现丰富的表格展示效果。

自定义传入:

  • 表格列的配置项(columns)
  • 表格数据数组(dataSource)
  • 分页器,为false时不展示和进行分页(pagination)
  • 只有一页时是否隐藏分页器(hideOnSinglePage)
  • 数据总数(total),默认为0
  • 页面是否加载中(loading),默认为false

整体样式模仿ant-design,效果图如下:

1.初始加载数据时的表格样式:

2.有数据并带分页时的表格样式:

3.有数据无分页时的表格样式:

4.无数据时的表格样式:

①创建带分页表格组件Table.vue:

<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" :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]">
            <slot v-if="col.slot" v-bind:data="data" :name="col.slot">{
  { data[col.dataIndex] || '--' }}</slot>
            <span v-else>{
  { data[col.dataIndex] || '--' }}</span>
          </td>
        </tr>
      </tbody>
    </table>
    <Pagination
      @change="changePage"
      :current="pagination.p"
      :pageSize="pagination.pageSize"
      :total="total"
      :hideOnSinglePage="hideOnSinglePage"
      :showQuickJumper="true"
      :showTotal="true"
      placement="right"
      v-if="pagination && total" />
  </div>
</template>
<script>
import Pagination from './Pagination'
import Spin from './Spin'
export default {
  name: 'Table',
  components: {
    Pagination,
    Spin
  },
  props: {
    columns: { // 表格列的配置项
      type: Array,
      default: () => {
        return []
      }
    },
    dataSource: { // 表格数据数组
      type: Array,
      default: () => {
        return []
      }
    },
    pagination: { // 分页器,为false时不展示和进行分页
      type: [Boolean, Object],
      default: false
    },
    hideOnSinglePage: { // 只有一页时是否隐藏分页器
      type: Boolean,
      default: false
    },
    total: { // 数据总数
      type: Number,
      default: 0
    },
    loading: { // 页面是否加载中
      type: Boolean,
      default: false
    }
  },
  methods: {
    changePage (pager) { // 分页器回调
      this.$emit('change', pager)
    }
  }
}
</script>
<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: #e6f7ff;
      }
    }
  }
}
</style>

②在要使用的页面引入:

<Table
      :columns="columns"
      :dataSource="tableData"
      :pagination="{
        p: queryParams.p,
        pageSize: queryParams.pageSize
      }"
      :hideOnSinglePage="false"
      :total="total"
      :loading="loading"
      @change="onChangeTable"
    >
      <!-- 配置指定列数据 -->
      <!-- <template #name="{ data: record }">
        hello {
  { record.name }}
      </template>
      <template v-slot:job="{ data: record }">
        hi {
  { record.job }}
      </template> -->
</Table>
import Table from '@/components/Table'
components: {
    Table
}
loading: false,
total: 10,
queryParams: {
    pageSize: 3,
    p: 1,
    mod: 'search'
},
columns: [
        {
          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'
        }
],
tableData: [
        {
          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'
        }
]
onChangeTable (pagination) {
      console.log('pagination:', pagination)
      this.queryParams.p = pagination.p
      this.queryParams.pageSize = pagination.pageSize
      this.getData()
},
getData () {
      this.tableLoading = true
      // 调用分页接口获取列表数据
}
相关文章
|
设计模式 存储 安全
八种创建单例模式的方式-懒汉式与饿汉式及枚举
八种创建单例模式的方式-懒汉式与饿汉式及枚举
560 2
|
人工智能 并行计算 PyTorch
【PyTorch&TensorBoard实战】GPU与CPU的计算速度对比(附代码)
【PyTorch&TensorBoard实战】GPU与CPU的计算速度对比(附代码)
1569 0
IntelliJ IDEA热部署插件JRebel免费激活图文教程
首先说下热部署是什么意思吧,简单了说就是在我们对代码进行更改之后,不需要重启项目,重新编译一下就可以直接运行最新的代码的部署方式。既然是部署方式,项目启动部署的时候当然就会和正常情况下不一样啦~
IntelliJ IDEA热部署插件JRebel免费激活图文教程
|
4月前
|
人工智能 缓存 API
个人/企业AI选型手册:阿里云千问大模型能力全解、接入代码、省钱订阅实操教程
阿里云千问(Qwen)是通义实验室自研全栈大模型体系,依托百炼一站式大模型平台对外提供稳定、合规、可弹性扩展的推理服务,完整覆盖文本理解、代码开发、多模态生成、逻辑智能体四大类业务场景,适配个人学习、独立开发者、中小企业、政企金融等不同规模使用主体。本文结合2026年最新产品体系,从核心能力矩阵、主流模型版本、四类计费模式、API接入实操、成本优化技巧、分场景选型建议六个板块完整拆解,帮助使用者精准匹配模型、选择最优付费方案,降低AI落地综合成本。
1194 1
|
机器学习/深度学习 人工智能 资源调度
AI大模型训练管理工具:千亿参数时代的指挥中枢
本内容揭示了大模型训练中三大核心挑战:实验复现难、资源利用率低、合规风险高,并提出“三维控制塔”解决方案,涵盖实验管理、资源调度与合规追踪。推荐Immuta + 板栗看板等工具组合助力不同规模团队实现高效、合规、低成本的AI训练。
|
存储 小程序 前端开发
微信小程序与Java后端实现微信授权登录功能
微信小程序极大地简化了登录注册流程。对于用户而言,仅仅需要点击授权按钮,便能够完成登录操作,无需经历繁琐的注册步骤以及输入账号密码等一系列复杂操作,这种便捷的登录方式极大地提升了用户的使用体验
4134 12
|
人工智能 算法 调度
实时云渲染助力全息影像突破终端算力瓶颈
全息技术、体积视频与高斯溅射是三维动态内容实时生成与传输的关键技术,但硬件成本、数据量大及多终端适配等问题制约其发展。实时云渲染成为关键解决方案,通过云端GPU资源池化与弹性调度,大幅降低算力门槛。LarkXR平台整合动态捕捉与AI算法,实现毫米级精度的三维重建,并优化传输架构,解决弱网环境下的延迟与带宽问题。在体育赛事、虚拟时尚及全息演唱会等领域,LarkXR助力开发者打造沉浸式体验,如NBA全息战术、巴黎高定秀场和虚拟偶像演唱会,推动全息技术从专业领域走向大众消费场景,开创全新商业价值。
|
开发者 iOS开发
uniapp打包苹果应用到哪里去获取私钥证书和证书profile文件
ios的应用,分两种安装方式,一种是上架app store的安装方式,一种是上传到一些应用内测的平台,进行扫码安装。
912 4
|
开发框架 JavaScript 前端开发
在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。
在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。