欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue+Ant Design開發(fā)簡單表格組件的實戰(zhàn)指南

 更新時間:2025年06月25日 10:34:58   作者:碼農(nóng)阿豪@新空間  
在現(xiàn)代前端開發(fā)中,數(shù)據(jù)表格是展示信息最常用的組件之一,本文主要為大家介紹了一個基于Vue和Ant Design的表格組件開發(fā)過程,感興趣的可以了解下

前言

在現(xiàn)代前端開發(fā)中,數(shù)據(jù)表格是展示信息最常用的組件之一。本文將詳細記錄一個基于Vue和Ant Design的表格組件開發(fā)過程,從最初的需求實現(xiàn)到遇到問題,再到最終優(yōu)化方案的完整思考過程。通過這個實際案例,我們將探討如何構(gòu)建一個高效、用戶友好的數(shù)據(jù)表格組件,特別是處理固定列和滾動區(qū)域的復雜交互。

一、項目背景與需求分析

我們的項目需要開發(fā)一個媒體廣告抓取記錄查看功能,主要需求包括:

  • 展示媒體廣告位的抓取記錄數(shù)據(jù)
  • 支持分頁和排序功能
  • 關鍵信息需要固定顯示(左右兩側(cè))
  • 中間區(qū)域可橫向滾動查看更多數(shù)據(jù)字段
  • 良好的性能表現(xiàn),支持大數(shù)據(jù)量

基于這些需求,我們選擇了Ant Design Vue作為UI組件庫,其強大的Table組件非常適合這類需求。

二、基礎實現(xiàn)

2.1 組件結(jié)構(gòu)設計

首先我們創(chuàng)建了GraspingRecordModal.vue組件,基礎結(jié)構(gòu)如下:

<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 數(shù)據(jù)獲取與處理

數(shù)據(jù)獲取使用異步請求,處理函數(shù)如下:

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 || '獲取數(shù)據(jù)失敗');
    }
  } catch (error) {
    console.error('獲取抓取記錄失敗:', error);
    this.$message.error(error.message);
  } finally {
    this.loading = false;
  }
}

2.3 初始列配置

最初的列配置嘗試固定左右兩側(cè)的關鍵信息:

columns: [
  {
    title: '任務ID',
    dataIndex: 'graspingTaskId',
    width: 180,
    fixed: 'left'
  },
  // ...其他中間列...
  {
    title: '狀態(tài)',
    dataIndex: 'graspingStatus',
    scopedSlots: { customRender: 'graspingStatus' },
    width: 100,
    fixed: 'right'
  }
]

三、遇到的問題與初步解決方案

3.1 空白表格區(qū)域問題

在初步實現(xiàn)中,我們發(fā)現(xiàn)表格左右兩側(cè)出現(xiàn)了不必要的空白區(qū)域,這嚴重影響了用戶體驗和視覺效果。

問題表現(xiàn):

  • 固定列與非固定列之間存在間隙
  • 滾動區(qū)域兩側(cè)出現(xiàn)空白
  • 表格整體布局不緊湊

3.2 原因分析

經(jīng)過調(diào)試,我們發(fā)現(xiàn)了幾個關鍵問題:

  • 寬度計算不準確:固定列和非固定列的寬度總和與表格容器寬度不匹配
  • 滾動設置不當:scroll.x值設置不合理
  • CSS樣式?jīng)_突:Ant Design默認樣式與我們的需求有沖突

3.3 初步修復嘗試

我們首先嘗試調(diào)整列寬和滾動設置:

:scroll="{ x: 1800 }"  // 根據(jù)列寬總和設置固定值

同時調(diào)整了一些列的寬度:

{
  title: '任務ID',
  dataIndex: 'graspingTaskId',
  width: 150,  // 縮小寬度
  fixed: 'left',
  ellipsis: true  // 添加省略號
}

四、深度優(yōu)化方案

4.1 完美的解決方案

經(jīng)過多次嘗試,我們找到了最合適的配置方案:

<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 優(yōu)化后的列配置

columns: [
  {
    title: '任務ID',
    dataIndex: 'graspingTaskId',
    width: 180,
    fixed: 'left',
    ellipsis: true
  },
  {
    title: '總?cè)罩緮?shù)',
    dataIndex: 'totalCount',
    width: 100,
    fixed: 'left',
    align: 'center'
  },
  // 中間可滾動列...
  {
    title: '狀態(tài)',
    dataIndex: 'graspingStatus',
    scopedSlots: { customRender: 'graspingStatus' },
    width: 100,
    fixed: 'right',
    align: 'center'
  },
  {
    title: '抓取時間',
    dataIndex: 'graspingTime',
    scopedSlots: { customRender: 'time' },
    width: 180,
    fixed: 'right'
  }
]

4.3 關鍵優(yōu)化點

  • 使用’max-content’:讓表格根據(jù)內(nèi)容自動計算寬度
  • 強制溢出設置:確保滾動行為符合預期
  • 最小寬度保證:防止容器意外收縮
  • 列對齊統(tǒng)一:所有數(shù)值列居中對齊
  • 固定列優(yōu)化:左右兩側(cè)固定列寬度適當加大

五、完整優(yōu)化代碼

以下是經(jīng)過全面優(yōu)化后的完整組件代碼:

<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: '總?cè)罩緮?shù)',
          dataIndex: 'totalCount',
          width: 100,
          fixed: 'left',
          align: 'center'
        },
        {
          title: '設備ID',
          dataIndex: 'deviceIdCount',
          width: 100,
          align: 'center'
        },
        {
          title: '啟動時間',
          dataIndex: 'bootTimeSecCount',
          width: 100,
          align: 'center'
        },
        {
          title: '系統(tǒng)更新時間',
          dataIndex: 'osUpdateTimeSecCount',
          width: 120,
          align: 'center'
        },
        {
          title: '初始化時間',
          dataIndex: 'birthTimeCount',
          width: 100,
          align: 'center'
        },
        {
          title: 'caids',
          dataIndex: 'caidsCount',
          width: 100,
          align: 'center'
        },
        {
          title: '系統(tǒng)編譯時間',
          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: '狀態(tài)',
          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 || '獲取數(shù)據(jù)失敗')
        }
      } 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>

六、總結(jié)與最佳實踐

通過這個案例,我們總結(jié)出以下Ant Design Table組件的最佳實踐:

1.固定列設計:

  • 關鍵信息固定在左右兩側(cè)
  • 固定列寬度適當加大
  • 添加ellipsis防止長文本溢出

2.滾動區(qū)域優(yōu)化:

  • 使用scroll="{ x: 'max-content' }"
  • 配合CSS強制溢出設置
  • 確保表格寬度自適應

3.性能考慮:

  • 合理設置分頁大小
  • 使用loading狀態(tài)提升用戶體驗
  • 大數(shù)據(jù)量時考慮虛擬滾動

4.視覺一致性:

  • 數(shù)值列居中對齊
  • 狀態(tài)使用標簽顏色區(qū)分
  • 時間統(tǒng)一格式化

5.健壯性保障:

  • 數(shù)據(jù)獲取錯誤處理
  • 空狀態(tài)處理
  • 分頁參數(shù)校驗

這個案例展示了如何通過迭代優(yōu)化解決實際問題,最終實現(xiàn)了一個既美觀又實用的數(shù)據(jù)表格組件。希望這些經(jīng)驗能幫助你在未來的項目中更好地使用Ant Design Table組件。

到此這篇關于Vue+Ant Design開發(fā)簡單表格組件的實戰(zhàn)指南的文章就介紹到這了,更多相關Vue Ant Design組件開發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 一篇帶你搞懂Vue項目里的權限控制

    一篇帶你搞懂Vue項目里的權限控制

    這篇文章主要為大家介紹了vue項目里的權限控制,文中有詳細的代碼示例供大家參考,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2023-06-06
  • Vue3組件掛載之創(chuàng)建組件實例詳解

    Vue3組件掛載之創(chuàng)建組件實例詳解

    這篇文章主要為大家介紹了Vue3組件掛載之創(chuàng)建組件實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • web面試MVC與MVVM區(qū)別及Vue為什么不完全遵守MVVM解答

    web面試MVC與MVVM區(qū)別及Vue為什么不完全遵守MVVM解答

    這篇文章主要介紹了web面試中常問問題,MVC與MVVM區(qū)別以及Vue為什么不完全遵守MVVM的難點解答,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • 100行代碼實現(xiàn)一個vue分頁組功能

    100行代碼實現(xiàn)一個vue分頁組功能

    今天用vue來實現(xiàn)一個分頁組件,總體來說,vue實現(xiàn)比較簡單,樣式部分模仿了elementUI。接下來本文通過實例代碼給大家介紹100行代碼實現(xiàn)一個vue分頁組功能,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • 一文詳解vue3項目實戰(zhàn)中的接口調(diào)用

    一文詳解vue3項目實戰(zhàn)中的接口調(diào)用

    在企業(yè)開發(fā)過程中,往往有著明確的前后端的分工,前端負責接收、使用接口,后端負責編寫、處理接口,下面這篇文章主要給大家介紹了關于vue3項目實戰(zhàn)中的接口調(diào)用的相關資料,需要的朋友可以參考下
    2022-12-12
  • Axios學習筆記之使用方法教程

    Axios學習筆記之使用方法教程

    axios是用來做數(shù)據(jù)交互的插件,最近正在學習axios,所以想著整理成筆記方便大家和自己參考學習,下面這篇文章主要跟大家介紹了關于Axios使用方法的相關資料,需要的朋友們下面來一起看看吧。
    2017-07-07
  • 詳解在Vue中如何使用axios跨域訪問數(shù)據(jù)

    詳解在Vue中如何使用axios跨域訪問數(shù)據(jù)

    本篇文章主要介紹了在Vue中如何使用axios跨域訪問數(shù)據(jù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 解決Vue2?axios發(fā)請求報400錯誤"Error:?Request?failed?with?status?code?400"

    解決Vue2?axios發(fā)請求報400錯誤"Error:?Request?failed?with?s

    這篇文章主要給大家介紹了關于如何解決Vue2?axios發(fā)請求報400錯誤"Error:?Request?failed?with?status?code?400"的相關資料,在Vue應用程序中我們通常會使用axios作為網(wǎng)絡請求庫,需要的朋友可以參考下
    2023-07-07
  • 詳解Vue.js動態(tài)綁定class

    詳解Vue.js動態(tài)綁定class

    Vue.js的核心是一個響應的數(shù)據(jù)綁定系統(tǒng),它允許我們在普通 HTML 模板中使用特殊的語法將 DOM “綁定”到底層數(shù)據(jù)。被綁定的DOM 將與數(shù)據(jù)保持同步,每當數(shù)據(jù)有改動,相應的DOM視圖也會更新?;谶@種特性,通過vue.js動態(tài)綁定class就變得非常簡單。一起來看下吧
    2016-12-12
  • Vue組件傳值方式(props屬性,父到子,子到父,兄弟傳值)

    Vue組件傳值方式(props屬性,父到子,子到父,兄弟傳值)

    這篇文章主要介紹了Vue組件傳值方式(props屬性,父到子,子到父,兄弟傳值),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06

最新評論