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
      // 调用分页接口获取列表数据
}
相关文章
Element UI之el-tabs的样式修改字体颜色、下划线、选中/未选中
Element UI之el-tabs的样式修改字体颜色、下划线、选中/未选中
4329 0
|
机器学习/深度学习 人工智能 资源调度
AI大模型训练管理工具:千亿参数时代的指挥中枢
本内容揭示了大模型训练中三大核心挑战:实验复现难、资源利用率低、合规风险高,并提出“三维控制塔”解决方案,涵盖实验管理、资源调度与合规追踪。推荐Immuta + 板栗看板等工具组合助力不同规模团队实现高效、合规、低成本的AI训练。
|
开发框架 JavaScript 前端开发
在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。
在Vue前端界面中,几种数据表格的展示处理,以及表格编辑录入处理操作。
|
存储 小程序 前端开发
微信小程序与Java后端实现微信授权登录功能
微信小程序极大地简化了登录注册流程。对于用户而言,仅仅需要点击授权按钮,便能够完成登录操作,无需经历繁琐的注册步骤以及输入账号密码等一系列复杂操作,这种便捷的登录方式极大地提升了用户的使用体验
4046 12
|
XML Java 数据格式
深入探索Spring的Bean注入:四种方式解析与循环依赖探讨
深入探索Spring的Bean注入:四种方式解析与循环依赖探讨
503 0
|
JavaScript 索引
如何在 Vue 中动态地添加或删除 Mixin
【10月更文挑战第18天】通过以上的分析和探讨,相信你对如何在 Vue 中动态地添加或删除 Mixin 有了更深入的理解。在实际开发中,你可以根据具体的需求和场景,灵活运用这些方法,以实现更加灵活和高效的应用开发。
581 4
|
SQL 前端开发 NoSQL
若依(ruoyi)管理系统(前后端分离版)本地运行教程(Windows)
若依(ruoyi)管理系统(前后端分离版)本地运行教程(Windows)
若依(ruoyi)管理系统(前后端分离版)本地运行教程(Windows)
|
存储 传感器 编解码
CVPR 2023 最全分割类论文整理:图像/全景/语义/实例分割等【附PDF+代码】
CVPR 2023 最全分割类论文整理:图像/全景/语义/实例分割等【附PDF+代码】
2243 1
|
Android开发
vue2,vue3移动端实现表格固定和首列固定
粘性布局,这个属性也可以实现行和列的固定,在pc端上没有啥问题,但是在手机端上会抖动。
vue2,vue3移动端实现表格固定和首列固定
|
小程序 API
uniapp 蓝牙小程序
uniapp 蓝牙小程序
1035 0