深入浅出 Element UI Table 组件:从基础到实战的完整指南

480 阅读4分钟

深入浅出 Element UI Table 组件:从基础到实战的完整指南

引言

作为前端开发中最常用的组件之一,表格承载着数据展示的核心功能。Element UI 的 Table 组件凭借其强大的功能和灵活的配置,成为后台管理系统的首选。本文将从零开始,带你逐步掌握 Table 组件的核心用法,并通过实战案例展示其在真实场景中的应用。


一、基础入门:快速上手 Table 组件

1. 安装与引入

<!-- 通过 CDN 引入 Element UI -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

2. 最简单的表格示例

<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="日期" width="180"/>
    <el-table-column prop="name" label="姓名" width="180"/>
    <el-table-column prop="address" label="地址"/>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        { date: '2023-10-01', name: '张三', address: '北京市朝阳区' },
        { date: '2023-10-02', name: '李四', address: '上海市浦东新区' }
      ]
    }
  }
}
</script>

关键点解析

  • :data 绑定数据源
  • el-table-columnprop 属性对应数据字段
  • width 属性设置列宽

二、数据绑定与动态渲染

1. 动态生成列

<template>
  <div>
    <el-button @click="addColumn">添加新列</el-button>
    <el-table :data="tableData" style="width: 100%">
      <el-table-column 
        v-for="(column, index) in columns" 
        :key="index" 
        :prop="column.prop" 
        :label="column.label"
      />
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      columns: [
        { prop: 'date', label: '日期' },
        { prop: 'name', label: '姓名' }
      ],
      tableData: [
        { date: '2023-10-01', name: '张三', age: 28 }
      ]
    }
  },
  methods: {
    addColumn() {
      this.columns.push({ prop: 'age', label: '年龄' })
    }
  }
}
</script>

实现原理

  • 使用 v-for 动态渲染表头
  • 通过修改 columns 数组动态增减列
  • 新增列时自动应用已有数据

三、核心功能:排序与分页

1. 启用排序功能

<el-table 
  :data="tableData" 
  style="width: 100%"
  @sort-change="handleSortChange"
>
  <el-table-column 
    prop="name" 
    label="姓名" 
    sortable="custom"
  />
</el-table>
methods: {
  handleSortChange({ column, prop, order }) {
    // 根据排序字段和顺序重新排序数据
    this.tableData.sort((a, b) => {
      if (order === 'ascending') return a[prop] > b[prop] ? 1 : -1
      if (order === 'descending') return a[prop] < b[prop] ? 1 : -1
      return 0
    })
  }
}

注意点

  • sortable="custom" 启用自定义排序
  • 监听 sort-change 事件获取排序状态
  • 需自行实现排序逻辑

2. 集成分页功能

<el-pagination
  @size-change="handleSizeChange"
  @current-change="handlePageChange"
  :current-page="currentPage"
  :page-size="pageSize"
  layout="total, sizes, prev, pager, next, jumper"
  :total="total"
/>
data() {
  return {
    currentPage: 1,
    pageSize: 10,
    total: 100 // 假设总数据量
  }
},
methods: {
  fetchData() {
    // 根据分页参数请求数据
    axios.get('/api/data', {
      params: {
        page: this.currentPage,
        limit: this.pageSize
      }
    }).then(res => {
      this.tableData = res.data.list
      this.total = res.data.total
    })
  },
  handleSizeChange(val) {
    this.pageSize = val
    this.fetchData()
  },
  handlePageChange(val) {
    this.currentPage = val
    this.fetchData()
  }
}

四、高级应用:自定义内容与动态数据

1. 使用作用域插槽定制单元格

<el-table :data="tableData">
  <el-table-column label="操作">
    <template slot-scope="scope">
      <el-button @click="handleEdit(scope.row)" type="text">编辑</el-button>
      <el-button @click="handleDelete(scope.row)" type="text">删除</el-button>
    </template>
  </el-table-column>
</el-table>

应用场景

  • 在操作列中添加编辑/删除按钮
  • 通过 scope.row 访问当前行数据
  • 支持嵌套复杂操作界面

2. 动态加载远程数据

methods: {
  loadData() {
    // 模拟 API 请求
    axios.get('/mock/api/data', {
      params: {
        search: this.searchKeyword,
        page: this.currentPage,
        pageSize: this.pageSize
      }
    }).then(res => {
      this.tableData = res.data.items
      this.total = res.data.total
    })
  }
}

完整流程

  1. 用户输入搜索关键词
  2. 触发分页参数变化
  3. 发送带参数的 API 请求
  4. 更新表格数据和总数

五、实战案例:后台用户管理系统

完整代码示例

<template>
  <div>
    <el-input v-model="searchKeyword" placeholder="搜索用户名" style="margin-bottom: 20px"/>
    
    <el-table 
      :data="filteredData" 
      style="width: 100%"
      @sort-change="handleSort"
    >
      <el-table-column prop="id" label="ID" width="80"/>
      <el-table-column prop="username" label="用户名" sortable="custom"/>
      <el-table-column prop="role" label="角色"/>
      <el-table-column prop="lastLogin" label="最后登录时间"/>
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button @click="editUser(scope.row)" type="text">编辑</el-button>
          <el-button @click="deleteUser(scope.row)" type="text">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handlePageChange"
      :current-page="currentPage"
      :page-size="pageSize"
      layout="total, sizes, prev, pager, next"
      :total="total"
      style="margin-top: 20px"
    />
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      tableData: [],
      filteredData: [],
      searchKeyword: '',
      currentPage: 1,
      pageSize: 10,
      total: 0,
      sortProp: '',
      sortOrder: ''
    }
  },
  created() {
    this.loadData();
  },
  computed: {
    filteredData() {
      // 执行搜索过滤
      const keyword = this.searchKeyword.toLowerCase();
      return this.tableData.filter(item => 
        item.username.toLowerCase().includes(keyword)
      );
    }
  },
  methods: {
    loadData() {
      // 模拟 API 请求
      axios.get('/mock/api/users', {
        params: {
          page: this.currentPage,
          limit: this.pageSize,
          sort: this.sortProp,
          order: this.sortOrder
        }
      }).then(res => {
        this.tableData = res.data.items;
        this.total = res.data.total;
      });
    },
    handleSizeChange(val) {
      this.pageSize = val;
      this.loadData();
    },
    handlePageChange(val) {
      this.currentPage = val;
      this.loadData();
    },
    handleSort({ column, prop, order }) {
      this.sortProp = prop;
      this.sortOrder = order;
      this.loadData();
    },
    editUser(user) {
      // 跳转编辑页面逻辑
      console.log('编辑用户:', user);
    },
    deleteUser(user) {
      // 删除用户逻辑
      console.log('删除用户:', user);
    }
  }
}
</script>

功能亮点

  1. 搜索过滤功能
  2. 服务端排序(传递排序参数给 API)
  3. 分页控制与数据加载
  4. 操作列的定制化按钮
  5. 真实 API 交互模拟

六、封装技巧与最佳实践

1. 提取表格组件为独立模块

// UserTable.vue
<template>
  <el-table :data="dataSource" ...>
    <!-- 列定义 -->
  </el-table>
</template>

<script>
export default {
  props: ['dataSource'],
  methods: {
    // 内部方法
  }
}
</script>

优势

  • 提高代码复用性
  • 隔离组件逻辑
  • 方便单元测试

2. 处理大数据优化

  • 使用懒加载技术
  • 虚拟滚动(仅渲染可视区域)
  • 服务端分页(优先)

3. 错误处理建议

axios.get('/api/data')
  .then(res => {
    // 处理成功逻辑
  })
  .catch(error => {
    this.$message.error('数据加载失败');
    console.error(error);
  });

七、扩展思考:与其他组件联动

1. 与表单结合实现增删改查

  • 使用 Dialog 组件作为编辑弹窗
  • 通过 Table 选择数据后填充表单

2. 与权限系统整合

computed: {
  visibleColumns() {
    return this.columns.filter(col => {
      // 根据用户权限过滤可见列
      return this.userPermissions.includes(col.permission);
    });
  }
}

3. 响应式布局适配

/* 适配移动端 */
@media screen and (max-width: 768px) {
  .el-table {
    font-size: 12px;
  }
  .el-table-column {
    flex: 1;
  }
}

结语

Element UI 的 Table 组件通过灵活的配置和丰富的钩子函数,能够满足各种复杂的数据展示需求。掌握本文所述的基础用法、核心功能和实战技巧,你将能够在实际项目中高效地构建功能强大的数据表格。建议结合具体业务场景,深入探索组件的扩展能力,打造更符合用户需求的数据管理界面。