Element Plus 数据展示组件完全指南(15个核心组件)

摘要:本文详细介绍 Element Plus 组件库中的 15 个数据展示组件,包含 Table、Tree、Pagination、Card 等高频使用组件。每个组件提供完整代码示例、核心 API 表格、实战场景及常见问题解答,帮助开发者掌握数据展示最佳实践。

关键词:Vue3、Element Plus、表格组件、树形控件、分页组件、数据展示、前端开发

适合人群:Vue3 中高级开发者、需要实现数据展示功能的开发者、前端工程师

阅读时间:约 30 分钟

版本信息:Element Plus 2.x | Vue 3.x | TypeScript


文章目录

  • [1. Table 表格](#1. Table 表格)
  • [2. TableV2 虚拟表格](#2. TableV2 虚拟表格)
  • [3. Tag 标签](#3. Tag 标签)
    • [3.1 组件简介](#3.1 组件简介)
    • [3.2 基础用法](#3.2 基础用法)
    • [3.3 常用场景](#3.3 常用场景)
    • 场景一:动态标签管理
    • [3.4 核心 API](#3.4 核心 API)
    • [3.5 注意事项](#3.5 注意事项)
  • [4. Progress 进度条](#4. Progress 进度条)
  • [5. Tree 树形控件](#5. Tree 树形控件)
  • [6. TreeV2 虚拟树形控件](#6. TreeV2 虚拟树形控件)
    • [6.1 组件简介](#6.1 组件简介)
    • [6.2 基础用法](#6.2 基础用法)
    • [6.3 核心 API](#6.3 核心 API)
    • [6.4 注意事项](#6.4 注意事项)
  • [7. Pagination 分页](#7. Pagination 分页)
  • [8. Badge 徽标](#8. Badge 徽标)
    • [8.1 组件简介](#8.1 组件简介)
    • [8.2 基础用法](#8.2 基础用法)
    • [8.3 核心 API](#8.3 核心 API)
    • [8.4 注意事项](#8.4 注意事项)
  • [9. Avatar 头像](#9. Avatar 头像)
    • [9.1 组件简介](#9.1 组件简介)
    • [9.2 基础用法](#9.2 基础用法)
    • [9.3 常用场景](#9.3 常用场景)
    • 场景一:头像组
    • [9.4 核心 API](#9.4 核心 API)
    • [9.5 注意事项](#9.5 注意事项)
  • [10. Skeleton 骨架屏](#10. Skeleton 骨架屏)
    • [10.1 组件简介](#10.1 组件简介)
    • [10.2 基础用法](#10.2 基础用法)
    • [10.3 核心 API](#10.3 核心 API)
    • [10.4 注意事项](#10.4 注意事项)
  • [11. Empty 空状态](#11. Empty 空状态)
    • [11.1 组件简介](#11.1 组件简介)
    • [11.2 基础用法](#11.2 基础用法)
    • [11.3 常用场景](#11.3 常用场景)
    • 场景一:自定义空状态
    • [11.4 核心 API](#11.4 核心 API)
    • [11.5 注意事项](#11.5 注意事项)
  • [12. Result 结果页](#12. Result 结果页)
    • [12.1 组件简介](#12.1 组件简介)
    • [12.2 基础用法](#12.2 基础用法)
    • [12.3 核心 API](#12.3 核心 API)
    • [12.4 注意事项](#12.4 注意事项)
  • [13. Calendar 日历](#13. Calendar 日历)
    • [13.1 组件简介](#13.1 组件简介)
    • [13.2 基础用法](#13.2 基础用法)
    • [13.3 常用场景](#13.3 常用场景)
    • 场景一:自定义日历单元格
    • [13.4 核心 API](#13.4 核心 API)
    • [13.5 注意事项](#13.5 注意事项)
  • [14. Card 卡片](#14. Card 卡片)
    • [14.1 组件简介](#14.1 组件简介)
    • [14.2 基础用法](#14.2 基础用法)
    • [14.3 常用场景](#14.3 常用场景)
    • 场景一:卡片列表
    • [14.4 核心 API](#14.4 核心 API)
    • [14.5 注意事项](#14.5 注意事项)
  • [15. Descriptions 描述列表](#15. Descriptions 描述列表)
    • [15.1 组件简介](#15.1 组件简介)
    • [15.2 基础用法](#15.2 基础用法)
    • [15.3 常用场景](#15.3 常用场景)
    • 场景一:自定义样式
    • [15.4 核心 API](#15.4 核心 API)
    • [15.5 注意事项](#15.5 注意事项)
  • [💡 综合实战案例](#💡 综合实战案例)
  • [❓ 常见问题 FAQ](#❓ 常见问题 FAQ)
    • [1. Table 数据量大时卡顿怎么办?](#1. Table 数据量大时卡顿怎么办?)
    • [2. Tree 节点过多导致性能问题?](#2. Tree 节点过多导致性能问题?)
    • [3. Pagination 如何与后端分页配合?](#3. Pagination 如何与后端分页配合?)
    • [4. 如何自定义 Empty 组件的图片?](#4. 如何自定义 Empty 组件的图片?)
    • [5. Skeleton 如何模拟真实布局?](#5. Skeleton 如何模拟真实布局?)
  • [📝 总结](#📝 总结)
  • [📚 参考资料](#📚 参考资料)

1. Table 表格

1.1 组件简介

Table 表格组件用于展示结构化数据,支持排序、筛选、分页、固定列等功能。

💡 提示:Table 是后台管理系统中最常用的组件之一,建议优先掌握。

1.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

interface User {
  id: number
  name: string
  age: number
  email: string
}

const tableData = ref<User[]>([
  { id: 1, name: '张三', age: 25, email: 'zhangsan@example.com' },
  { id: 2, name: '李四', age: 30, email: 'lisi@example.com' },
  { id: 3, name: '王五', age: 28, email: 'wangwu@example.com' }
])
</script>

<template>
  <el-table :data="tableData" border style="width: 100%">
    <el-table-column prop="id" label="ID" width="80" />
    <el-table-column prop="name" label="姓名" width="120" />
    <el-table-column prop="age" label="年龄" width="80" />
    <el-table-column prop="email" label="邮箱" />
  </el-table>
</template>

1.3 常用场景

场景一:带排序和筛选的表格

适用于后台管理系统的数据列表,支持按字段排序和条件筛选:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const tableData = ref([
  { id: 1, name: '张三', age: 25, city: '北京' },
  { id: 2, name: '李四', age: 30, city: '上海' },
  { id: 3, name: '王五', age: 28, city: '北京' }
])

const handleSort = ({ prop, order }: { prop: string; order: string }) => {
  console.log('排序字段:', prop, '排序方式:', order)
}

const handleFilter = (value: string, row: any) => {
  return row.city === value
}
</script>

<template>
  <el-table :data="tableData" @sort-change="handleSort">
    <el-table-column prop="id" label="ID" width="80" sortable />
    <el-table-column prop="name" label="姓名" width="120" />
    <el-table-column prop="age" label="年龄" width="80" sortable />
    <el-table-column 
      prop="city" 
      label="城市" 
      :filters="[
        { text: '北京', value: '北京' },
        { text: '上海', value: '上海' }
      ]"
      :filter-method="handleFilter"
    />
  </el-table>
</template>

效果说明

  • sortable 属性使列支持排序,点击列头可切换升序/降序
  • filters 定义筛选选项,filter-method 自定义筛选逻辑
  • 排序变化时会触发 sort-change 事件,可在此处请求后端数据

场景二:带操作列的表格

表格最后一列通常放置编辑、删除等操作按钮:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

const tableData = ref([
  { id: 1, name: '张三', age: 25 },
  { id: 2, name: '李四', age: 30 }
])

const handleEdit = (row: any) => {
  ElMessage(`编辑: ${row.name}`)
}

const handleDelete = (row: any) => {
  ElMessageBox.confirm(`确定删除 ${row.name} 吗?`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    tableData.value = tableData.value.filter(item => item.id !== row.id)
    ElMessage('删除成功')
  })
}
</script>

<template>
  <el-table :data="tableData" border>
    <el-table-column prop="id" label="ID" width="80" />
    <el-table-column prop="name" label="姓名" width="120" />
    <el-table-column prop="age" label="年龄" width="80" />
    <el-table-column label="操作" width="180">
      <template #default="{ row }">
        <el-button size="small" @click="handleEdit(row)">编辑</el-button>
        <el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

效果说明

  • 使用 #default 插槽自定义列内容,{ row } 获取当前行数据
  • 操作列建议固定宽度,避免按钮换行影响美观
  • 删除操作建议二次确认,防止误操作

场景三:带多选和展开行的表格

支持批量操作和查看详细信息:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const tableData = ref([
  { id: 1, name: '张三', age: 25, address: '北京市朝阳区' },
  { id: 2, name: '李四', age: 30, address: '上海市浦东新区' }
])

const selectedRows = ref([])

const handleSelectionChange = (selection: any[]) => {
  selectedRows.value = selection
  console.log('已选中:', selection.length, '条数据')
}
</script>

<template>
  <el-table 
    :data="tableData" 
    row-key="id"
    @selection-change="handleSelectionChange"
  >
    <el-table-column type="selection" width="55" />
    <el-table-column type="expand">
      <template #default="{ row }">
        <div style="padding: 20px">
          <p>详细地址:{{ row.address }}</p>
        </div>
      </template>
    </el-table-column>
    <el-table-column prop="id" label="ID" width="80" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column prop="age" label="年龄" />
  </el-table>
</template>

效果说明

  • type="selection" 添加多选框列,row-key 为必填项
  • type="expand" 添加展开行,点击可查看详细信息
  • selection-change 事件返回当前选中的所有行数据

1.4 核心 API

Table 属性

属性名 说明 类型 可选值 默认值
data 表格数据 Array - []
border 是否带有纵向边框 boolean - false
stripe 是否为斑马纹表格 boolean - false
height 表格高度 string/number - -
max-height 表格最大高度 string/number - -
show-header 是否显示表头 boolean - true
row-key 行数据的 Key string/function - -
size 表格尺寸 string large / default / small default
fit 列的宽度是否自撑开 boolean - true
highlight-current-row 是否高亮当前行 boolean - false
current-row-key 当前行的 key string/number - -
empty-text 空数据时显示的文本 string - 暂无数据

Table 事件

事件名 说明 回调参数
select 当用户手动勾选数据行的 Checkbox 时触发 selection, row
select-all 当用户手动勾选全选 Checkbox 时触发 selection
selection-change 当选择项发生变化时会触发 selection
row-click 当某一行被点击时会触发 row, column, event
sort-change 当表格的排序条件发生变化的时候会触发 { column, prop, order }

Table-Column 属性

属性名 说明 类型 可选值 默认值
prop 对应列内容的字段名 string - -
label 显示的标题 string - -
width 列的宽度 string/number - -
min-width 列的最小宽度 string/number - -
fixed 列是否固定 string/boolean left / right false
sortable 对应列是否可以排序 boolean - false
filters 过滤选项 Array - -
filter-method 过滤方法 Function - -
align 对齐方式 string left / center / right left
show-overflow-tooltip 超出时是否显示 tooltip boolean - false

1.5 注意事项

  1. 大数据量优化 :数据量超过 1000 条时建议使用 TableV2
  2. row-key 必填 :使用多选或展开行时必须设置 row-key
  3. 固定列宽度:固定列必须设置明确的宽度
  4. 性能优化:避免在表格中使用过多的自定义渲染

📚 官方文档Table 表格 - Element Plus


2. TableV2 虚拟表格

2.1 组件简介

TableV2 是基于虚拟滚动技术的高性能表格组件,适用于大数据量场景。

📖 相关知识:虚拟滚动只渲染可视区域的 DOM 节点,大幅提升性能。

2.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'
import { ElTableV2 } from 'element-plus'

const columns = [
  { key: 'id', title: 'ID', width: 80 },
  { key: 'name', title: '姓名', width: 120 },
  { key: 'age', title: '年龄', width: 80 }
]

const generateData = (count: number) => {
  const data = []
  for (let i = 0; i < count; i++) {
    data.push({
      id: i + 1,
      name: `用户${i + 1}`,
      age: 20 + (i % 30)
    })
  }
  return data
}

const data = ref(generateData(10000))
</script>

<template>
  <el-auto-resizer>
    <template #default="{ height, width }">
      <el-table-v2
        :columns="columns"
        :data="data"
        :width="width"
        :height="height"
        :row-height="50"
      />
    </template>
  </el-auto-resizer>
</template>

2.3 常用场景

场景一:万级数据渲染

适用于大数据量场景,如日志列表、订单列表等:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'
import { ElTableV2 } from 'element-plus'

const columns = [
  { key: 'id', title: 'ID', width: 100 },
  { key: 'name', title: '姓名', width: 150 },
  { key: 'email', title: '邮箱', width: 250 },
  { key: 'phone', title: '电话', width: 150 }
]

const data = ref(Array.from({ length: 50000 }, (_, i) => ({
  id: i + 1,
  name: `用户${i + 1}`,
  email: `user${i + 1}@example.com`,
  phone: `138${String(i).padStart(8, '0')}`
})))
</script>

<template>
  <el-table-v2
    :columns="columns"
    :data="data"
    :width="800"
    :height="600"
    :row-height="40"
  />
</template>

效果说明

  • 虚拟滚动只渲染可视区域的 DOM 节点,50000 条数据也能流畅滚动
  • 必须设置固定的 widthheightrow-height
  • 性能对比:普通 Table 渲染 5000 条数据约 2-3 秒,TableV2 仅需 100-200ms

场景二:自适应容器尺寸

使用 el-auto-resizer 实现响应式布局:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'
import { ElTableV2, ElAutoResizer } from 'element-plus'

const columns = [
  { key: 'id', title: 'ID', width: 80 },
  { key: 'name', title: '姓名', width: 120 },
  { key: 'age', title: '年龄', width: 80 }
]

const generateData = (count: number) => {
  const data = []
  for (let i = 0; i < count; i++) {
    data.push({
      id: i + 1,
      name: `用户${i + 1}`,
      age: 20 + (i % 30)
    })
  }
  return data
}

const data = ref(generateData(10000))
</script>

<template>
  <el-auto-resizer>
    <template #default="{ height, width }">
      <el-table-v2
        :columns="columns"
        :data="data"
        :width="width"
        :height="height"
        :row-height="50"
      />
    </template>
  </el-auto-resizer>
</template>

效果说明

  • el-auto-resizer 自动监听容器尺寸变化
  • 表格宽度和高度会根据容器自动调整
  • 适合全屏表格或响应式布局场景

2.4 核心 API

属性名 类型 说明 默认值
columns Column\[\] 列配置 \[\]
data RowData\[\] 数据源 \[\]
width number 表格宽度 必填
height number 表格高度 必填
row-height number 行高 50
header-height number 表头高度 50

2.5 注意事项

  1. 必须设置宽高:TableV2 需要明确的宽度和高度
  2. 固定行高 :不支持动态行高,需设置固定 row-height
  3. 不支持合并单元格:虚拟表格不支持单元格合并
  4. 适用场景:数据量 > 1000 条时使用

📚 官方文档TableV2 虚拟表格 - Element Plus


3. Tag 标签

3.1 组件简介

Tag 标签用于标记和选择,支持多种类型、尺寸和可关闭状态。

3.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const visible = ref(true)
</script>

<template>
  <div>
    <el-tag>默认标签</el-tag>
    <el-tag type="success">成功标签</el-tag>
    <el-tag type="info">信息标签</el-tag>
    <el-tag type="warning">警告标签</el-tag>
    <el-tag type="danger">危险标签</el-tag>
    <el-tag v-if="visible" closable @close="visible = false">可关闭标签</el-tag>
  </div>
</template>

3.3 常用场景

场景一:动态标签管理

用户可以添加、删除标签,常用于文章标签、技能标签等场景:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const tags = ref(['Vue', 'React', 'Angular'])
const inputVisible = ref(false)
const inputValue = ref('')

const handleClose = (tag: string) => {
  tags.value.splice(tags.value.indexOf(tag), 1)
}

const showInput = () => {
  inputVisible.value = true
}

const handleInputConfirm = () => {
  if (inputValue.value && !tags.value.includes(inputValue.value)) {
    tags.value.push(inputValue.value)
  }
  inputVisible.value = false
  inputValue.value = ''
}
</script>

<template>
  <div>
    <el-tag
      v-for="tag in tags"
      :key="tag"
      closable
      @close="handleClose(tag)"
      style="margin: 0 8px 8px 0"
    >
      {{ tag }}
    </el-tag>
    <el-input
      v-if="inputVisible"
      v-model="inputValue"
      size="small"
      style="width: 100px"
      @keyup.enter="handleInputConfirm"
      @blur="handleInputConfirm"
    />
    <el-button v-else size="small" @click="showInput">+ 添加标签</el-button>
  </div>
</template>

效果说明

  • closable 属性使标签可关闭,点击关闭图标触发 close 事件
  • 使用 v-if 控制输入框的显示/隐藏,点击按钮或失焦时确认添加
  • @keyup.enter 支持回车键快速添加,提升用户体验

3.4 核心 API

属性名 说明 类型 可选值 默认值
type 标签类型 string success / info / warning / danger ''
closable 是否可关闭 boolean - false
size 标签尺寸 string large / default / small default
effect 主题效果 string light / dark / plain light
color 背景色 string - -
hit 是否有边框描边 boolean - false
round 是否为圆角 boolean - false

3.5 注意事项

  1. 自定义颜色 :使用 color 属性可设置任意背景色
  2. effect 属性 :支持 lightdarkplain 三种效果
  3. 关闭事件 :关闭时触发 close 事件

📚 官方文档Tag 标签 - Element Plus


4. Progress 进度条

4.1 组件简介

Progress 进度条用于展示操作进度,支持线性和环形两种样式。

4.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const percentage = ref(50)
</script>

<template>
  <div>
    <el-progress :percentage="percentage" />
    <el-progress :percentage="100" status="success" />
    <el-progress :percentage="80" status="warning" />
    <el-progress :percentage="60" status="exception" />
    <el-progress :percentage="70" :stroke-width="20" />
  </div>
</template>

4.3 常用场景

场景一:环形进度条

适用于展示完成度、占比等场景:

vue 复制代码
<template>
  <div>
    <el-progress type="circle" :percentage="75" />
    <el-progress type="circle" :percentage="100" status="success" />
    <el-progress type="circle" :percentage="80" :stroke-width="15" />
  </div>
</template>

效果说明

  • type="circle" 切换为环形模式
  • status 可设置 success(成功)、exception(异常)、warning(警告)
  • stroke-width 控制环形宽度,数值越大环越粗

场景二:自定义颜色渐变

根据进度值动态改变颜色,增强视觉反馈:

vue 复制代码
<template>
  <el-progress
    :percentage="85"
    :color="customColors"
  />
</template>

<script setup lang="ts">
const customColors = [
  { color: '#f56c6c', percentage: 20 },
  { color: '#e6a23c', percentage: 40 },
  { color: '#5cb87a', percentage: 60 },
  { color: '#1989fa', percentage: 80 },
  { color: '#6f7ad3', percentage: 100 }
]
</script>

效果说明

  • color 支持数组,根据 percentage 值自动切换对应区间的颜色
  • 0-20% 显示红色(警告),40-60% 显示绿色(正常),80-100% 显示蓝色(优秀)
  • 适合文件上传、任务进度等需要视觉区分状态的场景

4.4 核心 API

属性名 说明 类型 可选值 默认值
percentage 百分比(必填) number 0-100 0
type 进度条类型 string line / circle / dashboard line
stroke-width 进度条宽度 number - 6
status 当前状态 string success / exception / warning -
color 进度条颜色 string/function/array - -
show-text 是否显示文字 boolean - true
text-inside 文字是否显示在进度条内 boolean - false
width 环形进度条宽度 number - 126

4.5 注意事项

  1. percentage 必填:必须设置 0-100 的数值
  2. status 优先级:设置 status 后会覆盖 color 属性
  3. 环形尺寸 :使用 width 属性设置环形进度条尺寸

📚 官方文档Progress 进度条 - Element Plus


5. Tree 树形控件

5.1 组件简介

Tree 树形控件用于展示具有层级关系的数据,支持展开/折叠、选中、拖拽等操作。

5.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const treeData = ref([
  {
    label: '一级 1',
    children: [
      {
        label: '二级 1-1',
        children: [{ label: '三级 1-1-1' }]
      }
    ]
  },
  {
    label: '一级 2',
    children: [
      { label: '二级 2-1' },
      { label: '二级 2-2' }
    ]
  }
])
</script>

<template>
  <el-tree :data="treeData" :props="{ children: 'children', label: 'label' }" />
</template>

5.3 常用场景

场景一:可选中树形控件

适用于权限管理、分类选择等需要多选的场景:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const treeRef = ref()

const treeData = ref([
  { id: 1, label: '北京', children: [{ id: 4, label: '朝阳区' }] },
  { id: 2, label: '上海', children: [{ id: 5, label: '浦东新区' }] },
  { id: 3, label: '广州' }
])

const getCheckedNodes = () => {
  console.log(treeRef.value.getCheckedNodes())
}
</script>

<template>
  <div>
    <el-tree
      ref="treeRef"
      :data="treeData"
      show-checkbox
      node-key="id"
      :props="{ children: 'children', label: 'label' }"
    />
    <el-button @click="getCheckedNodes">获取选中节点</el-button>
  </div>
</template>

效果说明

  • show-checkbox 显示复选框,支持多选
  • node-key 为必填项,用于唯一标识每个节点
  • 通过 ref 调用 getCheckedNodes() 获取选中节点

场景二:懒加载树形控件

适用于数据量大或需要异步加载的场景:

vue 复制代码
<script setup lang="ts">
const loadNode = (node: any, resolve: Function) => {
  if (node.level === 0) {
    return resolve([{ label: '根节点' }])
  }
  if (node.level >= 1) {
    return resolve([
      { label: `子节点 ${node.level}` },
      { label: `子节点 ${node.level + 1}` }
    ])
  }
}
</script>

<template>
  <el-tree :props="{ label: 'label' }" :load="loadNode" lazy />
</template>

效果说明

  • lazy 开启懒加载模式,节点展开时才会加载子节点
  • load 方法接收 noderesolve 两个参数
  • 适合树形数据量大、需要按需加载的场景(如文件系统、组织架构)

5.4 核心 API

属性名 说明 类型 可选值 默认值
data 树形数据 Array - []
props 配置选项 object - { children: 'children', label: 'label' }
show-checkbox 节点是否可被选择 boolean - false
node-key 每个树节点用来作为唯一标识的属性 string - -
lazy 是否懒加载 boolean - false
load 加载子树数据的方法 Function - -
accordion 是否每次只打开一个同级树节点 boolean - false
default-expand-all 是否默认展开所有节点 boolean - false
highlight-current 是否高亮当前选中节点 boolean - false

5.5 注意事项

  1. node-key 必填 :使用选中功能时必须设置 node-key
  2. 懒加载 :需要配合 load 方法使用
  3. 大数据优化 :节点超过 1000 个时建议使用 TreeV2

📚 官方文档Tree 树形控件 - Element Plus


6. TreeV2 虚拟树形控件

6.1 组件简介

TreeV2 是基于虚拟滚动的树形控件,适用于大数据量场景。

6.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const treeData = ref(
  Array.from({ length: 1000 }, (_, i) => ({
    id: `${i}`,
    label: `节点 ${i}`,
    children: []
  }))
)
</script>

<template>
  <el-tree-v2
    :data="treeData"
    :props="{ children: 'children', label: 'label' }"
    :height="400"
  />
</template>

6.3 核心 API

属性名 类型 说明 默认值
data Array 树形数据 \[\]
props object 配置选项 { children: 'children', label: 'label' }
height number 树控件高度 必填

6.4 注意事项

  1. 必须设置高度:TreeV2 需要明确的高度才能正常工作
  2. 不支持拖拽:虚拟树形控件暂不支持节点拖拽
  3. 适用场景:节点数量 > 1000 时使用

📚 官方文档TreeV2 虚拟树形控件 - Element Plus


7. Pagination 分页

7.1 组件简介

Pagination 分页组件用于数据分页展示,支持多种布局和自定义配置。

7.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(100)
</script>

<template>
  <el-pagination
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :page-sizes="[10, 20, 50, 100]"
    :total="total"
    layout="total, sizes, prev, pager, next, jumper"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
  />
</template>

<script setup lang="ts">
const handleSizeChange = (val: number) => {
  console.log(`每页 ${val} 条`)
}

const handleCurrentChange = (val: number) => {
  console.log(`当前页: ${val}`)
}
</script>

7.3 常用场景

场景一:小型分页

适用于数据量较少、不需要复杂分页的场景:

vue 复制代码
<template>
  <el-pagination
    :total="50"
    layout="prev, pager, next"
    :pager-count="5"
  />
</template>

效果说明

  • layout="prev, pager, next" 只显示上一页、页码、下一页
  • pager-count 控制显示的页码按钮数量,必须为奇数
  • 适合总页数少于10页的简单场景

场景二:完整分页配置

包含总数、每页条数选择器、跳转等完整功能:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(100)

const handleSizeChange = (val: number) => {
  console.log(`每页 ${val} 条`)
  // 重新请求数据
}

const handleCurrentChange = (val: number) => {
  console.log(`当前页: ${val}`)
  // 重新请求数据
}
</script>

<template>
  <el-pagination
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :page-sizes="[10, 20, 50, 100]"
    :total="total"
    layout="total, sizes, prev, pager, next, jumper"
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
  />
</template>

效果说明

  • v-model:current-pagev-model:page-size 支持双向绑定
  • layout 可自由组合:total(总数)、sizes(每页条数)、prev/next(上下页)、pager(页码)、jumper(跳转)
  • 分页变化时需要重新请求后端数据

7.4 核心 API

属性名 说明 类型 可选值 默认值
total 总条目数(必填) number - -
page-size 每页显示条目数 number - 10
current-page 当前页数 number - 1
page-sizes 每页显示个数选择器的选项 Array - [10, 20, 30, 40, 50, 100]
layout 组件布局 string total / sizes / prev / pager / next / jumper prev, pager, next, jumper
pager-count 页码按钮的数量 number 5-21的奇数 7
background 是否为分页按钮添加背景色 boolean - false
disabled 是否禁用 boolean - false

7.5 注意事项

  1. total 必填:必须设置总条目数
  2. layout 组合 :可自由组合 total, sizes, prev, pager, next, jumper
  3. 与表格配合:分页变化时重新请求数据

📚 官方文档Pagination 分页 - Element Plus


8. Badge 徽标

8.1 组件简介

Badge 徽标组件用于显示新消息数量或状态提示。

8.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const messageCount = ref(5)
</script>

<template>
  <el-badge :value="messageCount">
    <el-button>消息</el-button>
  </el-badge>
  <el-badge :value="0" :max="99">
    <el-button>通知</el-button>
  </el-badge>
  <el-badge is-dot>
    <el-button>红点</el-button>
  </el-badge>
</template>

8.3 核心 API

属性名 说明 类型 可选值 默认值
value 显示值 string/number - ''
max 最大值 number - 99
is-dot 小圆点 boolean - false
hidden 隐藏 badge boolean - false
type 类型 string primary / success / warning / danger / info danger

8.4 注意事项

  1. is-dot 模式:只显示红点,不显示数值
  2. hidden 属性:可动态控制徽标显示/隐藏
  3. 自定义内容:可使用默认插槽自定义内容

📚 官方文档Badge 徽标 - Element Plus


9. Avatar 头像

9.1 组件简介

Avatar 头像组件用于展示用户头像,支持图片、图标、文字三种形式。

9.2 基础用法

vue 复制代码
<template>
  <el-avatar src="https://example.com/avatar.jpg" />
  <el-avatar>U</el-avatar>
  <el-avatar :size="50">User</el-avatar>
  <el-avatar shape="square">S</el-avatar>
</template>

9.3 常用场景

场景一:头像组

适用于团队成员展示、群成员列表等场景:

vue 复制代码
<template>
  <el-avatar-group :max="3">
    <el-avatar src="https://example.com/1.jpg" />
    <el-avatar src="https://example.com/2.jpg" />
    <el-avatar src="https://example.com/3.jpg" />
    <el-avatar src="https://example.com/4.jpg" />
  </el-avatar-group>
</template>

效果说明

  • el-avatar-group 将多个头像组合展示
  • :max="3" 表示最多显示3个头像,超出的会显示为 +1 等形式
  • 头像会部分重叠,形成视觉上的群组效果

9.4 核心 API

属性名 说明 类型 可选值 默认值
src 图片地址 string - -
size 头像尺寸 number/string - 40
shape 形状 string circle / square circle
icon 图标类型 Component - -
fit 图片填充模式 string fill / contain / cover / none / scale-down cover
alt 图片 alt 属性 string - -

9.5 注意事项

  1. 图片加载失败:会自动显示 fallback 内容
  2. 头像组 :使用 el-avatar-group 组件
  3. 自定义尺寸:支持数值和 CSS 单位

📚 官方文档Avatar 头像 - Element Plus


10. Skeleton 骨架屏

10.1 组件简介

Skeleton 骨架屏用于在数据加载时显示占位内容,提升用户体验。

10.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const loading = ref(true)

setTimeout(() => {
  loading.value = false
}, 2000)
</script>

<template>
  <el-skeleton :loading="loading" :rows="5" animated>
    <template #template>
      <el-skeleton-item variant="image" style="width: 100px; height: 100px" />
      <el-skeleton-item variant="text" style="width: 200px" />
      <el-skeleton-item variant="text" style="width: 150px" />
    </template>
    <template #default>
      <div>实际内容</div>
    </template>
  </el-skeleton>
</template>

10.3 核心 API

属性名 类型 说明 默认值
loading boolean 是否显示骨架屏 true
rows number 占位行数 3
animated boolean 是否显示动画 false
throttle number 渲染延迟(ms) 0

10.4 注意事项

  1. loading 控制 :通过 loading 属性切换显示状态
  2. 自定义形状 :使用 variant 属性设置占位形状
  3. 动画效果 :设置 animated 提升加载体验

📚 官方文档Skeleton 骨架屏 - Element Plus


11. Empty 空状态

11.1 组件简介

Empty 空状态组件用于展示数据为空时的提示。

11.2 基础用法

vue 复制代码
<template>
  <el-empty description="暂无数据" />
  <el-empty :image-size="200" />
</template>

11.3 常用场景

场景一:自定义空状态

带有操作按钮的空状态,引导用户进行下一步操作:

vue 复制代码
<template>
  <el-empty description="暂无订单">
    <el-button type="primary" @click="goShopping">去逛逛</el-button>
  </el-empty>
</template>

<script setup lang="ts">
const goShopping = () => {
  console.log('跳转到购物页面')
}
</script>

效果说明

  • 使用默认插槽可以在空状态下方添加操作按钮
  • 引导用户进行操作,避免空白页面带来的困惑
  • 适合订单列表、消息列表等需要引导用户的场景

11.4 核心 API

属性名 说明 类型 可选值 默认值
image 图片地址 string - -
image-size 图片尺寸 number - 160
description 描述文字 string - 暂无数据

11.5 注意事项

  1. 自定义图片:可传入自定义图片 URL
  2. 默认插槽:可添加按钮或其他操作
  3. 配合表格:数据为空时显示 Empty 组件

📚 官方文档Empty 空状态 - Element Plus


12. Result 结果页

12.1 组件简介

Result 结果页用于展示操作结果,如成功、失败、警告等状态。

12.2 基础用法

vue 复制代码
<template>
  <el-result
    icon="success"
    title="操作成功"
    sub-title="您的订单已提交成功"
  >
    <template #extra>
      <el-button type="primary">返回首页</el-button>
    </template>
  </el-result>
</template>

12.3 核心 API

属性名 说明 类型 可选值 默认值
icon 图标类型 string success / warning / info / error info
title 标题 string - ''
sub-title 副标题 string - ''

12.4 注意事项

  1. icon 类型 :支持 successwarninginfoerror
  2. extra 插槽:用于放置操作按钮
  3. 配合路由:常用于操作结果页面

📚 官方文档Result 结果页 - Element Plus


13. Calendar 日历

13.1 组件简介

Calendar 日历组件用于展示日期信息,支持自定义单元格内容。

13.2 基础用法

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const selectedDate = ref(new Date())
</script>

<template>
  <el-calendar v-model="selectedDate" />
</template>

13.3 常用场景

场景一:自定义日历单元格

在日历中标记特殊日期,如节日、活动等:

vue 复制代码
<template>
  <el-calendar>
    <template #date-cell="{ data }">
      <div>
        {{ data.day.split('-').slice(1).join('-') }}
        <div v-if="data.day === '2024-01-01'" class="event">元旦</div>
      </div>
    </template>
  </el-calendar>
</template>

效果说明

  • 使用 #date-cell 插槽自定义每个日期单元格的显示内容
  • data.day 返回格式为 YYYY-MM-DD 的日期字符串
  • 可以根据业务需求在特定日期上添加标记、事件等

13.4 核心 API

属性名 说明 类型 可选值 默认值
v-model 绑定值 Date - -
range 时间范围 string - -

13.5 注意事项

  1. 自定义单元格 :使用 date-cell 插槽
  2. 范围限制 :使用 range 属性限制可选日期
  3. 配合表单:可作为日期选择器的替代方案

📚 官方文档Calendar 日历 - Element Plus


14. Card 卡片

14.1 组件简介

Card 卡片组件用于展示内容区块,支持自定义头部和阴影效果。

14.2 基础用法

vue 复制代码
<template>
  <el-card header="卡片标题">
    <p>卡片内容</p>
  </el-card>
  <el-card shadow="always">
    <p>始终显示阴影</p>
  </el-card>
</template>

14.3 常用场景

场景一:卡片列表

使用栅格布局展示响应式卡片网格:

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'

const cards = ref([
  { title: '卡片1', content: '内容1' },
  { title: '卡片2', content: '内容2' },
  { title: '卡片3', content: '内容3' }
])
</script>

<template>
  <el-row :gutter="20">
    <el-col v-for="card in cards" :key="card.title" :span="8">
      <el-card :header="card.title">
        <p>{{ card.content }}</p>
      </el-card>
    </el-col>
  </el-row>
</template>

效果说明

  • el-rowel-col 实现栅格布局,:span="8" 表示每行显示3个卡片
  • :gutter="20" 设置卡片之间的间距为20px
  • 适合产品展示、文章列表、用户列表等场景

14.4 核心 API

属性名 说明 类型 可选值 默认值
header 卡片标题 string - -
shadow 阴影显示时机 string always / hover / never always
body-style 卡片 body 样式 object - {}

14.5 注意事项

  1. header 插槽 :可使用 #header 插槽自定义头部
  2. 阴影控制shadow 支持 alwayshovernever
  3. 响应式布局 :配合 Layout 组件使用

📚 官方文档Card 卡片 - Element Plus


15. Descriptions 描述列表

15.1 组件简介

Descriptions 描述列表用于展示多个字段的键值对信息。

15.2 基础用法

vue 复制代码
<template>
  <el-descriptions title="用户信息" :column="2" border>
    <el-descriptions-item label="用户名">张三</el-descriptions-item>
    <el-descriptions-item label="手机号">13800138000</el-descriptions-item>
    <el-descriptions-item label="邮箱">zhangsan@example.com</el-descriptions-item>
    <el-descriptions-item label="地址">北京市朝阳区</el-descriptions-item>
  </el-descriptions>
</template>

15.3 常用场景

场景一:自定义样式

使用跨列、标签、徽标等元素丰富描述列表的展示效果:

vue 复制代码
<template>
  <el-descriptions :column="3" border>
    <el-descriptions-item label="产品" :span="2">
      <el-tag size="small">Element Plus</el-tag>
    </el-descriptions-item>
    <el-descriptions-item label="版本">2.x</el-descriptions-item>
    <el-descriptions-item label="状态">
      <el-badge value="new" />
    </el-descriptions-item>
  </el-descriptions>
</template>

效果说明

  • :span="2" 让"产品"单元格跨2列,突出重要信息
  • 可以在单元格内嵌套 Tag、Badge 等组件
  • border 模式带边框,更适合展示详细信息

15.4 核心 API

属性名 说明 类型 可选值 默认值
title 标题 string - -
column 列数 number - 3
border 是否带有边框 boolean - false
size 尺寸 string large / default / small default
direction 排列方向 string horizontal / vertical horizontal

15.5 注意事项

  1. span 属性:可设置单元格跨列
  2. border 模式:带边框更适合展示详细信息
  3. 配合卡片 :常与 Card 组件配合使用

📚 官方文档Descriptions 描述列表 - Element Plus


💡 综合实战案例

用户管理页面

结合 Table、Pagination、Tag、Badge、Avatar、Card、Descriptions 等组件实现完整的用户管理页面。

vue 复制代码
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

interface User {
  id: number
  name: string
  email: string
  role: string
  status: 'active' | 'inactive'
  avatar: string
}

const loading = ref(false)
const tableData = ref<User[]>([])
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
const selectedUser = ref<User | null>(null)
const dialogVisible = ref(false)

const fetchUsers = async () => {
  loading.value = true
  // 模拟 API 请求
  setTimeout(() => {
    tableData.value = Array.from({ length: pageSize.value }, (_, i) => ({
      id: (currentPage.value - 1) * pageSize.value + i + 1,
      name: `用户${i + 1}`,
      email: `user${i + 1}@example.com`,
      role: i % 2 === 0 ? '管理员' : '普通用户',
      status: i % 3 === 0 ? 'inactive' : 'active',
      avatar: `https://example.com/avatar${i % 5}.jpg`
    }))
    total.value = 100
    loading.value = false
  }, 500)
}

const handleDelete = (row: User) => {
  ElMessageBox.confirm(`确定删除 ${row.name} 吗?`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    ElMessage('删除成功')
    fetchUsers()
  })
}

const handlePageChange = (page: number) => {
  currentPage.value = page
  fetchUsers()
}

const handleSizeChange = (size: number) => {
  pageSize.value = size
  currentPage.value = 1
  fetchUsers()
}

const viewDetail = (row: User) => {
  selectedUser.value = row
  dialogVisible.value = true
}

fetchUsers()
</script>

<template>
  <el-card header="用户管理">
    <el-table :data="tableData" v-loading="loading" border>
      <el-table-column label="头像" width="80">
        <template #default="{ row }">
          <el-avatar :size="40" :src="row.avatar">{{ row.name[0] }}</el-avatar>
        </template>
      </el-table-column>
      <el-table-column prop="id" label="ID" width="80" />
      <el-table-column prop="name" label="姓名" width="120" />
      <el-table-column prop="email" label="邮箱" />
      <el-table-column label="角色" width="120">
        <template #default="{ row }">
          <el-tag :type="row.role === '管理员' ? 'danger' : 'primary'">
            {{ row.role }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" width="100">
        <template #default="{ row }">
          <el-badge :is-dot="row.status === 'active'" :hidden="row.status === 'inactive'">
            <el-tag :type="row.status === 'active' ? 'success' : 'info'">
              {{ row.status === 'active' ? '活跃' : '禁用' }}
            </el-tag>
          </el-badge>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="200">
        <template #default="{ row }">
          <el-button size="small" @click="viewDetail(row)">详情</el-button>
          <el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :total="total"
      :page-sizes="[10, 20, 50]"
      layout="total, sizes, prev, pager, next"
      @current-change="handlePageChange"
      @size-change="handleSizeChange"
      style="margin-top: 20px; justify-content: flex-end"
    />
  </el-card>

  <el-dialog v-model="dialogVisible" title="用户详情" width="600px">
    <el-descriptions v-if="selectedUser" :column="2" border>
      <el-descriptions-item label="ID">{{ selectedUser.id }}</el-descriptions-item>
      <el-descriptions-item label="姓名">{{ selectedUser.name }}</el-descriptions-item>
      <el-descriptions-item label="邮箱">{{ selectedUser.email }}</el-descriptions-item>
      <el-descriptions-item label="角色">{{ selectedUser.role }}</el-descriptions-item>
    </el-descriptions>
  </el-dialog>
</template>

❓ 常见问题 FAQ

1. Table 数据量大时卡顿怎么办?

解决方案

  1. 使用 TableV2 虚拟滚动
  2. 开启 lazy 懒加载
  3. 减少自定义列渲染
  4. 使用 row-key 优化渲染
vue 复制代码
<!-- 使用 TableV2 -->
<el-table-v2
  :columns="columns"
  :data="largeData"
  :width="800"
  :height="600"
/>

📖 扩展阅读TableV2 官方文档

2. Tree 节点过多导致性能问题?

解决方案

  1. 使用 TreeV2
  2. 开启懒加载
  3. 按需展开节点
vue 复制代码
<el-tree-v2 :data="largeTreeData" :height="500" />

3. Pagination 如何与后端分页配合?

解决方案:监听分页变化事件,重新请求数据。

vue 复制代码
<script setup lang="ts">
const handleCurrentChange = (page: number) => {
  fetchList({ page, pageSize: pageSize.value })
}
</script>

4. 如何自定义 Empty 组件的图片?

解决方案 :使用 image 属性传入自定义图片 URL。

vue 复制代码
<el-empty image="https://example.com/custom-empty.png" description="自定义空状态" />

5. Skeleton 如何模拟真实布局?

解决方案 :使用 variant 属性设置不同占位形状。

vue 复制代码
<el-skeleton-item variant="image" style="width: 100px; height: 100px" />
<el-skeleton-item variant="text" />
<el-skeleton-item variant="button" />

📝 总结

本文介绍了 Element Plus 的 15 个数据展示组件,涵盖表格、树形、分页、标签、进度条等常用场景。

组件使用频率

组件 使用频率 推荐指数
Table ⭐⭐⭐⭐⭐ 必学
Pagination ⭐⭐⭐⭐⭐ 必学
Tag ⭐⭐⭐⭐ 高频
Card ⭐⭐⭐⭐ 高频
Tree ⭐⭐⭐⭐ 高频
Badge ⭐⭐⭐ 常用
Avatar ⭐⭐⭐ 常用
Progress ⭐⭐⭐ 常用
Skeleton ⭐⭐⭐ 常用
Empty ⭐⭐⭐ 常用
Descriptions ⭐⭐ 一般
Result ⭐⭐ 一般
Calendar ⭐⭐ 一般
TableV2 特定场景
TreeV2 特定场景

学习建议

  1. 优先掌握 Table、Pagination、Tree 三个核心组件
  2. 大数据量场景使用 TableV2 和 TreeV2
  3. 配合 Form 组件 实现完整的数据管理功能
  4. 建议配合官方文档学习,获取最新 API 信息

📚 参考资料

官方文档

相关技术文档


📌 下一篇预告导航与反馈组件 - 包含 Breadcrumb、Menu、Dialog、Drawer 等 15 个导航与反馈相关组件的详细使用指南。

📚 系列导航基础组件 | 表单组件上 | 表单组件下 | 数据展示组件 | 导航与反馈组件 | 其他实用组件

相关推荐
qiuhaipeng11 小时前
Claude code 升级后上下文长度变短问题
java·前端·数据库
zzz_23681 小时前
个人 AI 记忆如何跨工具复用:用 Markdown、索引和 Skill 搭一个可治理的记忆库
前端·人工智能·react.js·前端框架·agent·agent测评
剑之所向3 小时前
.NET 官方`System.Threading.Channels`
前端·javascript·数据库
计算机魔术师4 小时前
GPT-6 Astra幻觉砍到2%,却被一种老招数轻松绕过
前端
cjy0001114 小时前
2026AI 产品如何从一次性 Demo 变成可重复使用的业务工具?
前端·人工智能·fde
IT_陈寒4 小时前
React的状态更新坑得我差点加班到天亮
前端·人工智能·后端
风骏时光牛马4 小时前
深挖底层逻辑:XX源码深度拆解分析
前端
渡我白衣4 小时前
并查集:基础认识与模拟实现
android·java·javascript·数据结构·c++·算法·并查集
电商API_180079052474 小时前
电商商品价格监控工具淘宝京东商品价格抓取API项目实操分享
java·大数据·开发语言·前端·数据挖掘