vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue Ant Design组件开发

Vue+Ant Design开发简单表格组件的实战指南

作者:码农阿豪@新空间

在现代前端开发中,数据表格是展示信息最常用的组件之一,本文主要为大家介绍了一个基于Vue和Ant Design的表格组件开发过程,感兴趣的可以了解下

前言

在现代前端开发中,数据表格是展示信息最常用的组件之一。本文将详细记录一个基于Vue和Ant Design的表格组件开发过程,从最初的需求实现到遇到问题,再到最终优化方案的完整思考过程。通过这个实际案例,我们将探讨如何构建一个高效、用户友好的数据表格组件,特别是处理固定列和滚动区域的复杂交互。

一、项目背景与需求分析

我们的项目需要开发一个媒体广告抓取记录查看功能,主要需求包括:

基于这些需求,我们选择了Ant Design Vue作为UI组件库,其强大的Table组件非常适合这类需求。

二、基础实现

2.1 组件结构设计

首先我们创建了GraspingRecordModal.vue组件,基础结构如下:

<template>
  <a-modal
    title="抓取记录"
    :visible="visible"
    width="90%"
    :footer="null"
    @cancel="handleCancel"
  >
    <a-table
      rowKey="id"
      :columns="columns"
      :dataSource="data"
      :pagination="pagination"
      :loading="loading"
      @change="handleTableChange"
    >
      <!-- 自定义渲染插槽 -->
    </a-table>
  </a-modal>
</template>

2.2 数据获取与处理

数据获取使用异步请求,处理函数如下:

async fetchData() {
  this.loading = true;
  try {
    const { data: res } = await getGraspingRecords({
      mediaAdId: this.mediaAdId,
      page: this.pagination.current,
      pageSize: this.pagination.pageSize
    });
    
    if (res.code === '000000') {
      this.data = res.data.aaData || [];
      this.pagination.total = res.data.iTotalRecords || 0;
    } else {
      throw new Error(res.msg || '获取数据失败');
    }
  } catch (error) {
    console.error('获取抓取记录失败:', error);
    this.$message.error(error.message);
  } finally {
    this.loading = false;
  }
}

2.3 初始列配置

最初的列配置尝试固定左右两侧的关键信息:

columns: [
  {
    title: '任务ID',
    dataIndex: 'graspingTaskId',
    width: 180,
    fixed: 'left'
  },
  // ...其他中间列...
  {
    title: '状态',
    dataIndex: 'graspingStatus',
    scopedSlots: { customRender: 'graspingStatus' },
    width: 100,
    fixed: 'right'
  }
]

三、遇到的问题与初步解决方案

3.1 空白表格区域问题

在初步实现中,我们发现表格左右两侧出现了不必要的空白区域,这严重影响了用户体验和视觉效果。

问题表现:

3.2 原因分析

经过调试,我们发现了几个关键问题:

3.3 初步修复尝试

我们首先尝试调整列宽和滚动设置:

:scroll="{ x: 1800 }"  // 根据列宽总和设置固定值

同时调整了一些列的宽度:

{
  title: '任务ID',
  dataIndex: 'graspingTaskId',
  width: 150,  // 缩小宽度
  fixed: 'left',
  ellipsis: true  // 添加省略号
}

四、深度优化方案

4.1 完美的解决方案

经过多次尝试,我们找到了最合适的配置方案:

<a-table
  :scroll="{ x: 'max-content' }"
  :columns="columns"
  bordered
  size="middle"
>

配合以下CSS修正:

.grasping-record-modal >>> .ant-table {
  min-width: 100%;
}
.grasping-record-modal >>> .ant-table-container {
  overflow-x: auto !important;
}
.grasping-record-modal >>> .ant-table-body {
  overflow-x: auto !important;
}

4.2 优化后的列配置

columns: [
  {
    title: '任务ID',
    dataIndex: 'graspingTaskId',
    width: 180,
    fixed: 'left',
    ellipsis: true
  },
  {
    title: '总日志数',
    dataIndex: 'totalCount',
    width: 100,
    fixed: 'left',
    align: 'center'
  },
  // 中间可滚动列...
  {
    title: '状态',
    dataIndex: 'graspingStatus',
    scopedSlots: { customRender: 'graspingStatus' },
    width: 100,
    fixed: 'right',
    align: 'center'
  },
  {
    title: '抓取时间',
    dataIndex: 'graspingTime',
    scopedSlots: { customRender: 'time' },
    width: 180,
    fixed: 'right'
  }
]

4.3 关键优化点

五、完整优化代码

以下是经过全面优化后的完整组件代码:

<template>
  <a-modal
    title="抓取记录"
    :visible="visible"
    width="90%"
    :footer="null"
    @cancel="handleCancel"
    :destroyOnClose="true"
    class="grasping-record-modal"
  >
    <a-table
      rowKey="id"
      :columns="columns"
      :dataSource="data"
      :pagination="pagination"
      :loading="loading"
      :scroll="{ x: 'max-content' }"
      @change="handleTableChange"
      bordered
      size="middle"
    >
      <template slot="graspingStatus" slot-scope="text">
        <a-tag :color="getStatusColor(text)">
          {{ getStatusText(text) }}
        </a-tag>
      </template>
      <template slot="time" slot-scope="text">
        {{ formatDateTime(text) }}
      </template>
    </a-table>
  </a-modal>
</template>

<script>
import dayjs from 'dayjs'
import { getGraspingRecords } from '@/api/ad-api/media'

export default {
  name: 'GraspingRecordModal',
  data() {
    return {
      loading: false,
      data: [],
      pagination: {
        current: 1,
        pageSize: 10,
        total: 0,
        showSizeChanger: true,
        pageSizeOptions: ['10', '20', '50', '100'],
        showTotal: total => `共 ${total} 条记录`
      },
      columns: [
        {
          title: '任务ID',
          dataIndex: 'graspingTaskId',
          width: 180,
          fixed: 'left',
          ellipsis: true
        },
        {
          title: '总日志数',
          dataIndex: 'totalCount',
          width: 100,
          fixed: 'left',
          align: 'center'
        },
        {
          title: '设备ID',
          dataIndex: 'deviceIdCount',
          width: 100,
          align: 'center'
        },
        {
          title: '启动时间',
          dataIndex: 'bootTimeSecCount',
          width: 100,
          align: 'center'
        },
        {
          title: '系统更新时间',
          dataIndex: 'osUpdateTimeSecCount',
          width: 120,
          align: 'center'
        },
        {
          title: '初始化时间',
          dataIndex: 'birthTimeCount',
          width: 100,
          align: 'center'
        },
        {
          title: 'caids',
          dataIndex: 'caidsCount',
          width: 100,
          align: 'center'
        },
        {
          title: '系统编译时间',
          dataIndex: 'sysComplingTimeCount',
          width: 120,
          align: 'center'
        },
        {
          title: 'IDFA',
          dataIndex: 'idfaCount',
          width: 100,
          align: 'center'
        },
        {
          title: 'IMSI',
          dataIndex: 'imsiCount',
          width: 100,
          align: 'center'
        },
        {
          title: '安装包列表',
          dataIndex: 'appListCount',
          width: 120,
          align: 'center'
        },
        {
          title: '状态',
          dataIndex: 'graspingStatus',
          scopedSlots: { customRender: 'graspingStatus' },
          width: 100,
          fixed: 'right',
          align: 'center'
        },
        {
          title: '抓取时间',
          dataIndex: 'graspingTime',
          scopedSlots: { customRender: 'time' },
          width: 180,
          fixed: 'right'
        }
      ]
    }
  },
  props: {
    visible: {
      type: Boolean,
      default: false
    },
    mediaAdId: {
      type: [Number, String],
      required: true
    }
  },
  methods: {
    formatDateTime(timeStr) {
      return timeStr ? dayjs(timeStr).format('YYYY-MM-DD HH:mm:ss') : '-'
    },
    getStatusText(status) {
      const map = { 0: '失败', 1: '成功', 2: '部分成功' }
      return map[status] || '未知'
    },
    getStatusColor(status) {
      const map = { 0: 'red', 1: 'green', 2: 'orange' }
      return map[status] || 'default'
    },
    handleTableChange(pagination) {
      this.pagination.current = pagination.current
      this.pagination.pageSize = pagination.pageSize
      this.fetchData()
    },
    async fetchData() {
      this.loading = true
      try {
        const { data: res } = await getGraspingRecords({
          mediaAdId: this.mediaAdId,
          page: this.pagination.current,
          pageSize: this.pagination.pageSize
        })
        if (res.code === '000000') {
          this.data = res.data.aaData || []
          this.pagination.total = res.data.iTotalRecords || 0
        } else {
          throw new Error(res.msg || '获取数据失败')
        }
      } catch (error) {
        console.error('获取抓取记录失败:', error)
        this.$message.error(error.message)
      } finally {
        this.loading = false
      }
    },
    handleCancel() {
      this.$emit('close')
    }
  }
}
</script>

<style scoped>
.grasping-record-modal >>> .ant-table {
  min-width: 100%;
}
.grasping-record-modal >>> .ant-table-container {
  overflow-x: auto !important;
}
.grasping-record-modal >>> .ant-table-body {
  overflow-x: auto !important;
}
</style>

六、总结与最佳实践

通过这个案例,我们总结出以下Ant Design Table组件的最佳实践:

1.固定列设计:

2.滚动区域优化:

3.性能考虑:

4.视觉一致性:

5.健壮性保障:

这个案例展示了如何通过迭代优化解决实际问题,最终实现了一个既美观又实用的数据表格组件。希望这些经验能帮助你在未来的项目中更好地使用Ant Design Table组件。

到此这篇关于Vue+Ant Design开发简单表格组件的实战指南的文章就介绍到这了,更多相关Vue Ant Design组件开发内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文