动态控制表格表头显隐,让表格变得更加智能

本文介绍如何使用Vue组件实现表格列的动态隐藏,通过多选框控制列的显示状态,适合处理大量数据时节省屏幕空间。主要涉及Popover、Checkbox、Button和Table组件的配合应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在日常办公中,我们经常需要操作各种表格。然而,当表格数据过多时,表头往往会挤占宝贵的屏幕空间,给我们的工作带来不便。那么,如何实现动态控制表头的显隐呢?本文将为大家详细介绍。


如何实现?

本章节用的组件

  • Popover 弹出框
  • Checkbox 多选框
  • Button 按钮
  • Table 表格

实现思路

当多选框的选项改变时,通过 columnChange 方法更新 colData 中每个列的 ishide 属性。如果多选框中的选项在 colData 中存在,将对应列的 ishide 属性设为 true,否则设为 false。然后,在表格中使用 v-if 指令根据 colData 中每个列的 ishide 属性来决定是否显示该列即可。


话不多说,下面直接看实例代码


完整源码

<template>
  <div>
    <!-- Popover 弹出框 -->
    <div class="popoverBox">
      <el-popover placement="right" trigger="click">
        <el-checkbox-group v-model="colOptions">
          <el-checkbox v-for="item in colData" :label="item.title" :key="item.title" @change="columnChange">{{ item.title }}</el-checkbox>
        </el-checkbox-group>
        <!-- reference	触发 Popover 显示的 HTML 元素 -->
        <el-button icon="el-icon-menu" type="info" size="mini" slot="reference">显示列</el-button>
      </el-popover>
    </div>
    <!-- Table 表格 -->
    <div class="tableBox">
      <el-table :data="tableData" border>
        <el-table-column label="姓名" v-if="colData[0].ishide" prop="name"></el-table-column>
        <el-table-column label="性别" v-if="colData[1].ishide" prop="sex"></el-table-column>
        <el-table-column label="年龄" v-if="colData[2].ishide" prop="age"></el-table-column>
        <el-table-column label="电话" v-if="colData[3].ishide" prop="phone"></el-table-column>
        <el-table-column label="邮箱" v-if="colData[4].ishide" prop="email"></el-table-column>
        <el-table-column label="学历" v-if="colData[5].ishide" prop="education"></el-table-column>
        <el-table-column label="职业" v-if="colData[6].ishide" prop="occupation"></el-table-column>
        <el-table-column label="地址" v-if="colData[7].ishide" prop="site"></el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 模拟表格数据
      tableData: [
        {
          name: "小红",
          sex: "女",
          age: "20",
          phone: "177****8810",
          email: "2901626033@qq.com",
          education: "本科",
          occupation: "前端开发",
          site: "北京昌平",
        },
      ],
      //动态显示列
      colData: [
        { title: "姓名", ishide: true },
        { title: "性别", ishide: true },
        { title: "年龄", ishide: true },
        { title: "电话", ishide: true },
        { title: "邮箱", ishide: false },
        { title: "学历", ishide: true },
        { title: "职业", ishide: false },
        { title: "地址", ishide: true },
      ],
      // 多选框绑定值
      colOptions: ["姓名", "性别", "年龄", "电话", "学历", "地址"],
    };
  },
  methods: {
    //动态显示列
    columnChange() {
      this.colData.forEach((item) => {
        if (this.colOptions.indexOf(item.title) !== -1) {
          item.ishide = true;
        } else {
          item.ishide = false;
        }
      });
    },
  },
};
</script>

<style scoped>
.popoverBox {
  display: flex;
  justify-content: right;
  margin: 10px 0px;
}
</style>

实现效果

在这里插入图片描述


封装公共组件

封装组件

<template>
  <div class="popoverBox">
    <el-popover placement="right" trigger="click">
      <el-checkbox-group v-model="colOptions">
        <el-checkbox v-for="item in colData" :label="item.title" :key="item.title" @change="columnChange">{{ item.title }}</el-checkbox>
      </el-checkbox-group>
      <el-button icon="el-icon-menu" type="info" size="mini" slot="reference">{{ buttonText }}</el-button>
    </el-popover>
  </div>
</template>

<script>
export default {
  props: {
    colData: {
      type: Array,
      default: () => [],
    },
    buttonText: {
      type: String,
      default: "显示列",
    },
  },
  data() {
    return {
      // 用于存储选中的checkbox选项
      colOptions: this.colData
        .filter((item) => item.ishide === true)
        .map((item) => item.title),
    };
  },
  methods: {
    // 用于监听checkbox选项的变化
    columnChange() {
      this.colData.forEach((item) => {
        if (this.colOptions.indexOf(item.title) !== -1) {
          item.ishide = true;
        } else {
          item.ishide = false;
        }
      });
    },
  },
};
</script>
<style scoped>
.popoverBox {
  display: flex;
  justify-content: right;
  margin: 10px 0px;
}
</style>

使用组件

<template>
  <div class="containerBox">
    <!-- Popover 弹出框 -->
    <column-select :col-data="colData" :button-text="buttonText"></column-select>
    <!-- Table 表格 -->
    <div class="tableBox">
      <el-table :data="tableData" border>
        <el-table-column label="姓名" v-if="colData[0].ishide" prop="name"></el-table-column>
        <el-table-column label="性别" v-if="colData[1].ishide" prop="sex"></el-table-column>
        <el-table-column label="年龄" v-if="colData[2].ishide" prop="age"></el-table-column>
        <el-table-column label="电话" v-if="colData[3].ishide" prop="phone"></el-table-column>
        <el-table-column label="邮箱" v-if="colData[4].ishide" prop="email"></el-table-column>
        <el-table-column label="学历" v-if="colData[5].ishide" prop="education"></el-table-column>
        <el-table-column label="职业" v-if="colData[6].ishide" prop="occupation"></el-table-column>
        <el-table-column label="地址" v-if="colData[7].ishide" prop="site"></el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import ColumnSelect from "@/components/columnSelect";

export default {
  components: {
    ColumnSelect,
  },
  data() {
    return {
      // 多选框展示的值
      buttonText: "显示列",
      // 模拟表格数据
      tableData: [
        {
          name: "小红",
          sex: "女",
          age: "20",
          phone: "177****8810",
          email: "2901626033@qq.com",
          education: "本科",
          occupation: "前端开发",
          site: "北京昌平",
        },
      ],
      //动态显示列
      colData: [
        { title: "姓名", ishide: true },
        { title: "性别", ishide: true },
        { title: "年龄", ishide: true },
        { title: "电话", ishide: true },
        { title: "邮箱", ishide: false },
        { title: "学历", ishide: true },
        { title: "职业", ishide: false },
        { title: "地址", ishide: true },
      ],
    };
  },
};
</script>

拓展

filter() 方法通过检查指定数组中符合条件的所有元素,filter()方法不会改变原始数组。

参数描述
参数1必须。当前元素的值。
参数2可选。当前元素的索引值。
参数3可选。当前元素属于的数组对象。

简单实例

let array = [{ id: 1, name: "小红" },{ id: 2, name: "小黄" },{ id: 3, name: "小兰" },{ id: 4, name: "小绿" },];
let fil = array.filter((item) => item.id != 1); // 查找数组中id不等于1的对象
console.log(fil); // [{id: 2, name: '小黄'},{id: 3, name: '小兰'},{id: 4, name: '小绿'}]


indexOf() 方法可以返回某个指定的字符串值在字符串中首次出现的位置,如果没有找到匹配的字符串则返回 -1。

参数描述
参数1必须。要查找的字符串的值(e)。
参数2可选。整数。在字符串的第几个位置(5)开始查找字符(e)第一次出现的位置,如省略该参数,则将从字符串的首字符开始检索。

简单实例

var str = 'Hello world, welcome to the universe';
var det = str.indexOf('e', 5); // 在字符串第五个位置开始查找字符'e'第一次出现的位置
console.log(det); // 14

在网页设计中,当使用CSS的`display`属性来通过“”、“”切换两个表格时,可能会遇到元素切换时产生的视觉抖动。这是因为浏览器需要重新计算每个元素的布局位置,尤其是在从`none`到`block`或相反的变化过程中。 为了减少这种抖动,你可以采用以下策略: 1. **延迟展示**:可以给示或表格的动画添加一定的延迟时间,让浏览器有足够的时间完成当前的渲染再开始新的改变。 ```css .table { transition: display 0.3s ease; } .show { display: block !important; /* 添加延迟 */ animation-delay: 0.2s; } .hide { display: none !important; /* 或者添加负延迟 */ animation-delay: -0.2s; } ``` 2. **使用JavaScript**:利用JavaScript的`requestAnimationFrame`或者类似库(如Lodash的`throttle`函数),对切换操作进限制频率,降低抖动效果。 ```javascript function toggleTable() { // ... if (!toggleTimer) { toggleTimer = requestAnimationFrame(() => { toggleTable(); toggleTimer = null; }); } } // 触发切换的地方 document.getElementById('table-switcher').addEventListener('click', toggleTable); ``` 3. **优化动画**:使用CSS `transform: translateZ(0)` 可以避免重排(reflow),并结合will-change属性告诉浏览器哪些属性会变化,减少抖动。 ```css .table { will-change: transform; transition: opacity 0.3s ease, transform 0s; /* 尽量同时更改可见性和位移 */ } /* ... 然后像之前一样切换 display 属性 */ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水星记_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值