基于el-table的表格点选和框选功能

开篇

本篇文章旨在实现一个基于el-table的表格点选和框选功能,除此之外,还支持多种模式的切换、自定义勾选日期等。且,该表格后续可能还会持续优化!

功能介绍

  • 表格点选和框选功能(没有点击ctrl键的情况下)
  • 表格点选和框选功能的互斥功能,意思是当现在选择了该单元格后,按住ctrl键再次点击,就会取消选择
  • 当前日期高亮
  • 周、双周、月份模式的切换以及自定义日期的选择
  • 对于可点选和框选功能的范围判断(表头和名称不可选择)

代码实现

index.vue

<template>
  <div class="container">
    <!-- 顶部功能栏区域 -->
    <data class="top-bar">
      <!-- 切换模式按钮 -->
      <el-button size="mini" type="primary" @click="turnWeek"></el-button>
      <el-button size="mini" type="primary" @click="turnTwoWeeks"
        >两周</el-button
      >
      <el-button size="mini" type="primary" @click="turnMonth"></el-button>
      <!-- 自定义时间范围选择器 -->
      <div class="time-range-picker">
        <span class="arrow-icon">
          <el-icon><ArrowLeftBold /></el-icon>
        </span>
        <!-- 起始日期 -->
        <el-date-picker
          class="time-picker"
          v-model="dateForm.startDate"
          type="datetime"
          :shortcuts="shortcuts"
          @change="(value) => handleDateChange('startDate', value)"
        />
        <span style="padding: 0 10px">-</span>
        <!--结束日期 -->
        <el-date-picker
          class="time-picker"
          v-model="dateForm.endDate"
          type="datetime"
          :shortcuts="shortcuts"
          @change="(value) => handleDateChange('endDate', value)"
        />
        <span class="arrow-icon">
          <el-icon><ArrowRightBold /></el-icon>
        </span>
      </div>
    </data>
    <!-- 表格区域 -->
    <div class="table-container">
      <!-- 月份选择 -->
      <month-schedule-table
        :table-data="tableData"
        :switch-model="switchModel"
        :dateForm="dateForm"
        :customDateFlag="customDateFlag"
        @updateDateForm="handleUpdateDateForm"
        :table-width="tableWidth"
      ></month-schedule-table>
    </div>
  </div>
</template>

<script>
import {
   
   
  defineComponent,
  onMounted,
  reactive,
  toRefs,
  ref,
  watchEffect,
  onUpdated,
  onUnmounted,
  nextTick,
} from "vue";
import MonthScheduleTable from "./components/MonthScheduleTable.vue";
export default defineComponent({
   
   
  name: "DepartmentScheduleConfig",
  components: {
   
   
    MonthScheduleTable,
  },
  setup() {
   
   
    const state = reactive({
   
   
      tableData: [],
      switchModel: "month",
      // 自定义日期选择相关
      dateForm: {
   
   
        startDate: "",
        endDate: "",
      },
      customDateFlag: false, // 是否在自定义切换日期的标识
    });

    const tableWidth = ref(0);
    onMounted(() => {
   
   
      // 先初始化一些假数据用着
      initData();

      nextTick(() => {
   
   
        getTableWidth();
      });
    });

    const getTableWidth = () => {
   
   
      // 求表格宽度
      let container = document.querySelector(".container");
      if (container) {
   
   
        const observer = new ResizeObserver(() => {
   
   
          tableWidth.value = container.clientWidth;
        });

        observer.observe(container);

        // 初始获取一次宽度
        tableWidth.value = container.clientWidth;
      }
    };

    // 每次更新表格时,也要重新获取表格宽度
    onUpdated(() => {
   
   
      getTableWidth();
    });

    window.addEventListener("resize", getTableWidth);

    // 页面关闭时,移除事件监听器
    onUnmounted(() => {
   
   
      window.removeEventListener("resize", getTableWidth);
    });

    // 切换成周模式
    const turnWeek = () => {
   
   
      state.switchModel = "week";
      state.customDateFlag = false;
    };

    // 切换成两周模式
    const turnTwoWeeks = () => {
   
   
      state.switchModel = "twoWeeks";
      state.customDateFlag = false;
    };

    // 切换成月模式
    const turnMonth = () => {
   
   
      state.switchModel = "month";
      state.customDateFlag = false;
    };

    // 初始化数据
    const initData = () => {
   
   
      const obj = {
   
   };

      for (let i = 0; i <= 31; i++) {
   
   
        obj[`date${
     
     i}`] = null;
      }

      const arr = [];
      for (let j = 1; j < 10; j++) {
   
   
        const tmpObj = {
   
    ...obj };
        tmpObj.id = j;
        tmpObj.name = `zzz${
     
     j}`;
        arr.push(tmpObj);
      }
      console.log("arr", arr);
      arr[0].date1 = "X";
      arr[3].date3 = "Y";
      state.tableData = arr;
    };

    /**
     * 自定义日期相关
     */
    // 日期选择面板扩展
    const shortcuts = [
      {
   
   
        text: "今天",
        value: new Date(),
      },
      {
   
   
        text: "昨天",
        value: () => {
   
   
          const date = new Date();
          date.setDate(date.getDate() - 1);
          
<think>我们正在使用Element UI的el-table组件,并希望禁用某些行的复选框。根据引用内容,我们可以通过`selectable`属性来实现。该属性绑定一个方法,该方法根据行的数据返回布尔值(true表示可选,false表示禁用)。 步骤: 1. 在el-table-column中设置type="selection",并添加:selectable="方法名"。 2. 在methods中定义该方法,根据row(当前行数据)判断是否禁用。如果返回false,则该行复选框被禁用。 注意:引用[1]引用[4]提供了具体的方法实现示例。引用[2]引用[3]分别提供了样式修改另一种返回值的写法(但注意引用[3]中返回0/1,实际上Element UI要求返回布尔值,但也可以接受0(false)1(true)?不过官方文档建议返回布尔值)。 因此,我们可以这样实现: 模板部分: ```html <el-table :data="tableData"> <el-table-column type="selection" :selectable="isSelectable" width="55"></el-table-column> <!-- 其他列 --> </el-table> ``` 在Vue实例的methods中定义isSelectable方法: ```javascript methods: { isSelectable(row, index) { // 根据row的某些属性判断是否禁用 // 例如,如果row中有一个disabled字段为true,则禁用 if (row.disabled) { return false; } return true; } } ``` 另外,引用[2]提到如果复选框被禁用且被选中,可以通过样式修改其外观(比如改变背景色边框色)。如果不需要修改样式,可以忽略。 注意:禁用后,用户将无法通过点击复选框来改变选中状态(包括取消选中)。所以,如果某行已经被选中,然后我们禁用了它,那么用户将无法取消选中。因此,在设置禁用时,通常需要结合业务逻辑考虑是否预先选中这些行。 如果希望禁用的行一开始就被选中且不可更改,可以在数据初始化时设置选中(通过el-table的toggleRowSelection方法),然后禁用。 示例:在表格数据加载后,对需要禁用的行设置选中状态(如果它们需要被默认选中且禁用): ```javascript this.$nextTick(() => { this.tableData.forEach(row => { if (row.disabled) { this.$refs.table.toggleRowSelection(row, true); } }); }); ``` 注意:这里假设表格的ref属性设置为"table",即`<el-table ref="table" ...>`。 总结: 1. 使用selectable方法控制每行是否可选中(禁用)。 2. 如果需要默认选中禁用的行,可以在数据加载后通过toggleRowSelection方法设置选中。 3. 如果需要修改禁用状态下被选中的复选框样式,可以按照引用[2]的样式进行修改。 相关问题: 1. 如何设置el-table中某些行的复选框为默认选中且不可更改? 2. 如何修改el-table中禁用的复选框的样式? 3. el-table的selectable方法返回什么值?可以返回数字01吗? 4. 在el-table中,如何实现全选按钮不包含禁用的行?</think>在 Element UI 的 el-table 中禁用复选框,可通过 `selectable` 属性实现。以下是完整解决方案: ### 实现步骤 1. **添加选择列** 在 el-table 中定义 `type="selection"` 的列,并绑定 `:selectable` 属性: ```html <el-table :data="tableData"> <el-table-column type="selection" :selectable="isRowSelectable" <!-- 关键属性 --> width="55"> </el-table-column> <!-- 其他列 --> </el-table> ``` 2. **定义禁用逻辑** 在 Vue 的 `methods` 中实现 `isRowSelectable` 方法,通过返回值控制是否禁用: ```javascript methods: { isRowSelectable(row, index) { // 示例1:根据状态字段禁用 if (row.status === &#39;disabled&#39;) return false // 示例2:禁用已选中的行(需配合选中状态数据) const isSelected = this.selectedData.some(item => item.id === row.id) return !isSelected } } ``` ### 完整示例 ```html <template> <el-table :data="tableData" @selection-change="handleSelectionChange"> <el-table-column type="selection" :selectable="isRowSelectable" width="55"> </el-table-column> <el-table-column prop="name" label="名称"></el-table-column> <el-table-column prop="status" label="状态"></el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { id: 1, name: &#39;项目A&#39;, status: &#39;active&#39; }, { id: 2, name: &#39;项目B&#39;, status: &#39;disabled&#39; }, // 此行将被禁用 { id: 3, name: &#39;项目C&#39;, status: &#39;active&#39; } ], selectedData: [] // 存储已选数据 } }, methods: { // 禁用逻辑 isRowSelectable(row) { // 条件1:状态为 disabled 时禁用 // 条件2:已选中的行禁用(防止重复选择) return row.status !== &#39;disabled&#39; && !this.selectedData.some(item => item.id === row.id) }, // 更新选中数据 handleSelectionChange(selection) { this.selectedData = selection } } } </script> <style> /* 可选:修改禁用复选框样式 */ .el-checkbox.is-disabled .el-checkbox__inner { background-color: #f5f7fa; border-color: #e4e7ed; } </style> ``` ### 关键说明 1. **`selectable` 属性** - 必须绑定一个返回布尔值的函数 - `return true`:该行可选(默认) - `return false`:禁用该行复选框 2. **典型禁用场景** - 根据行数据状态禁用(如 `row.status === &#39;inactive&#39;`) - 禁用已选中的行(需配合 `selection-change` 事件) - 基于权限控制(如 `row.permissionLevel < 3`) 3. **样式自定义** 如需修改禁用样式,通过 CSS 覆盖默认样式: ```css /* 禁用状态下的选中样式 */ .el-checkbox.is-disabled.is-checked .el-checkbox__inner { background-color: #d7063b !important; border-color: #d7063b !important; } ``` ### 注意事项 1. 禁用行的复选框**无法通过点击改变状态**,但可通过 `toggleRowSelection` 编程控制 2. 禁用行的选中状态不会包含在 `selection-change` 事件返回的数据中 3. 全选操作会自动跳过已禁用的行[^1][^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值