本文介绍: 在许多 Web 应用中,数据分页常见操作方式。当用户一个页面选择了一些数据项,然后切换到另一页时,保持之前选中的项通常是用户友好的体验。同时,可能存在一些需要禁选的执行项,例如在某些状态下,用户应该选择执行某些操作:如当数据可以进行执行相关操作,并且需要消耗一定时间时,我们为了任务完整执行,会在任务执行期间,禁止选中任务选择框(可以预防用户进行删除操作),后续执行完毕可以恢复初始选中状态,也可以放弃选中状态

引言

        在前文中,我们曾深入探讨了在修改数据后跨页时提醒用户可能丢失数据的问题。虽然这种方式对于一些场景是足够的,但当涉及选择框时,我们需要更为智能和高效的解决方案。在本文中,我们分享一种基于 Element UI 的实际案例,旨在实现跨页保存选中项与禁选特定项的需求通过以下详细讨论,你将了解到这一方案实现原理及其用户体验效果

问题背景

        在许多 Web 应用中,数据分页是常见的操作方式。当用户在一个页面选择了一些数据项,然后切换到另一页时,保持之前选中的项通常是用户友好的体验。同时,可能存在一些需要禁选的执行项,例如在某些状态下,用户应该选择或执行某些操作:如当数据可以进行执行相关操作,并且需要消耗一定时间时,我们为了任务完整执行,会在任务执行期间,禁止选中任务选择框(可以预防用户进行删除等操作),后续执行完毕可以恢复初始选中状态,也可以放弃选中状态

方案设计实现

        在 Element UI 中,表格(Table组件提供了丰富的特性事件。可以利用这些特性事件来实现跨页保存选中项和禁选执行项的需求

实现

        1.跨页保存

        在许多 Web 应用中,数据分页是常见的操作方式。当用户在一个页面中选择了一些数据项,然后切换到另一页时,保持之前选中的项通常是用户友好的体验。

        模板
    <el-table
      ref="multipleTable"
      :data="tableData"
      @select="handleSelectionChange"
      @select-all="handleSelectionAll"
    >
      <el-table-column type="selection" align="center"></el-table-column>
      <el-table-column prop="name" label="name" align="center"></el-table-column>
      <el-table-column prop="age" label="age" align="center"></el-table-column>
    </el-table>
    
    <el-pagination
      :background="true"
      :current-page.sync="queryParams.page"
      :page-size.sync="queryParams.pageSize"
      layout="total,prev,pager,next,sizes"
      :total="total"
      :page-sizes="[5, 10, 20, 40]"
      @size-change="getList"
      @current-change="getList" />
        脚本
data() {
    return {
      total: void 0,
      queryParams: {
        page: 1,
        pageSize: 10,
      },
      allData: [],
      tableData: [],
      multipleSelection: [],
      listId: [],
    };
  },
  mounted() {
    this.getList();
  },
  methods: {
    getList() {
      this.allData = [
        { name: 'A', age: 1 },
        { name: 'B', age: 2 },
        { name: 'C', age: 3 },
        { name: 'D', age: 4 },
        { name: 'E', age: 5 },
        { name: 'F', age: 6 },
        { name: 'G', age: 7 },
        { name: 'H', age: 8 },
        { name: 'I', age: 9 },
        { name: 'J', age: 10 },
        { name: 'K', age: 11 },
        { name: 'L', age: 12 },
        { name: 'M', age: 13 },
        { name: 'N', age: 14 },
        { name: 'O', age: 15 },
        { name: 'P', age: 16 },
        { name: 'Q', age: 17 },
        { name: 'R', age: 18 },
        { name: 'S', age: 19 },
        { name: 'T', age: 20 },
        { name: 'U', age: 21 },
        { name: 'V', age: 22 },
        { name: 'W', age: 23 },
        { name: 'X', age: 24 },
        { name: 'Y', age: 25 },
        { name: 'Z', age: 26 },
      ];

      this.total = this.allData.length;
      let currentPageIndex = (this.queryParams.page - 1) * this.queryParams.pageSize;
      let currentPageSize = this.queryParams.pageSize - 1 || 1;
      this.tableData = this.allData.slice(currentPageIndex, currentPageIndex + currentPageSize + 1);

      this.listId = [];
      this.tableData.forEach(item => this.listId.push(item.name));

      this.$nextTick(() => {
        this.tableData.forEach((item, index) => {
          if (this.multipleSelection.findIndex(v => v == item.name) >= 0) {
            this.$refs.multipleTable.toggleRowSelection(this.$refs.multipleTable.data[index], true);
          }
        });
      });
    },

    // 全选
    handleSelectionAll(val) {
      if (val.length) {
        const result = [];
        this.listId.forEach(id => {
          if (this.multipleSelection.every(item => item !== id)) result.push(id);
        });

        this.multipleSelection.push(...result);
      } else {
        this.listId.forEach(id => {
          this.multipleSelection = this.multipleSelection.filter(item => item !== id);
        });
      }
    },

    // 单选
    handleSelectionChange(rows, row) {
      if (this.multipleSelection.find(item => item === row.name)) this.multipleSelection = this.multipleSelection.filter(item => item != row.name); // 过滤(删除)
      else this.multipleSelection.push(row.name);
    },
}
        解析
  1. getList 方法

  2. handleSelectionAll 方法:

  3. handleSelectionChange 方法:

        这些方法共同实现了跨页保存选中状态的功能通过维护 multipleSelection 数组保存用户选择的行的 id,从而在表格分页切换时保持选中状态。

        2.禁选执行项

        数据拥有执行状态之类的字段,并且需要消耗一定时间时,我们为了任务完整执行,会在任务执行期间,禁止选中该任务的选择框(以避免删除等操作)。执行完毕后可以恢复初始选中状态,也可以放弃选中状态。

         以下代码选择的是后者,即在重新开始运行时,禁用该项选择框并且执行完毕后不重新选中。如果希望保留,在对应执行的函数(下述为 reloadTask)中不删除 multipleSelection对应的id即可

        模板
    <el-table
      ref="multipleTable"
      :data="tableData"
      @select="handleSelectionChange"
      @select-all="handleSelectionAll"
    >
      <el-table-column type="selection" align="center" :selectable="selectable"></el-table-column>
      <el-table-column prop="name" label="name" align="center"></el-table-column>
      <el-table-column prop="age" label="age" align="center"></el-table-column>
      <el-table-column label="status">
        <template slot-scope="scope">
          <span
            style="margin-right:10px; cursor: pointer;"
            :class="scope.row.status !== '执行中' ? 'el-icon-caret-right' : 'el-icon-loading'"
            size="small"
            :disabled="scope.row.status === '执行中'"
            @click="reloadTask(scope.row)"></span>
          <el-tag :type="scope.row.status !== '执行中' ? '' : 'info'">{{scope.row.status}}</el-tag>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      :background="true"
      :current-page.sync="queryParams.page"
      :page-size.sync="queryParams.pageSize"
      layout="total,prev,pager,next,sizes"
      :total="total"
      :page-sizes="[5, 10, 20, 40]"
      @size-change="getList"
      @current-change="getList" />
        脚本
data() {
    return {
      total: void 0,
      queryParams: {
        page: 1,
        pageSize: 10,
      },
      allData: [],
      tableData: [],
      multipleSelection: [],
      listId: [],
      loadingSelection: new Set(),
    };
  },
  mounted() {
    this.getList();
  },
  methods: {
    getList(flag = false) {
      if (!flag) {
        this.allData = [
          { name: 'A', age: 1, status: '执行完毕' },
          { name: 'B', age: 2, status: '执行中' },
          { name: 'C', age: 3, status: '执行完毕' },
          { name: 'D', age: 4, status: '未执行' },
          { name: 'E', age: 5, status: '未执行' },
          { name: 'F', age: 6, status: '执行中' },
          { name: 'G', age: 7, status: '执行中' },
          { name: 'H', age: 8, status: '执行中' },
          { name: 'I', age: 9, status: '执行中' },
          { name: 'J', age: 10, status: '未执行' },
          { name: 'K', age: 11, status: '未执行' },
          { name: 'L', age: 12, status: '未执行' },
          { name: 'M', age: 13, status: '未执行' },
          { name: 'N', age: 14, status: '未执行' },
          { name: 'O', age: 15, status: '未执行' },
          { name: 'P', age: 16, status: '未执行' },
          { name: 'Q', age: 17, status: '未执行' },
          { name: 'R', age: 18, status: '未执行' },
          { name: 'S', age: 19, status: '未执行' },
          { name: 'T', age: 20, status: '未执行' },
          { name: 'U', age: 21, status: '未执行' },
          { name: 'V', age: 22, status: '未执行' },
          { name: 'W', age: 23, status: '未执行' },
          { name: 'X', age: 24, status: '未执行' },
          { name: 'Y', age: 25, status: '未执行' },
          { name: 'Z', age: 26, status: '未执行' },
        ];
      }

      this.total = this.allData.length;
      let currentPageIndex = (this.queryParams.page - 1) * this.queryParams.pageSize;
      let currentPageSize = this.queryParams.pageSize - 1 || 1;
      this.tableData = this.allData.slice(currentPageIndex, currentPageIndex + currentPageSize + 1);

      this.listId = [];
      this.tableData.forEach(item => this.listId.push(item.name));

      this.$nextTick(() => {
        this.tableData.forEach((item, index) => {
          if (this.multipleSelection.findIndex(v => v == item.name) >= 0) {
            this.$refs.multipleTable.toggleRowSelection(this.$refs.multipleTable.data[index], true);
          }
        });
      });
    },

    // 执行任务
    reloadTask(row) {
      this.multipleSelection = this.multipleSelection.filter(item => item !== row.name);
      row.status = '执行中';
      this.getList(true);
    },
    
    // 判断可选性
    selectable(row) {
      if (row.status !== '执行中') {
        if (this.loadingSelection.has(row.name)) this.loadingSelection.delete(row.name);
        return true;
      } else {
        this.loadingSelection.add(row.name);
        return false;
      }
    },

    // 全选
    handleSelectionAll(val) {
      if (val.length) {
        const result = [];
        this.listId.forEach(id => {
          if (this.multipleSelection.every(item => item !== id) &amp;&amp; !this.loadingSelection.has(id)) result.push(id);
        });

        this.multipleSelection.push(...result);
      } else {
        this.listId.forEach(id => {
          this.multipleSelection = this.multipleSelection.filter(item => item !== id);
        });
      }
    },

    // 单选
    handleSelectionChange(rows, row) {
      if (this.multipleSelection.find(item => item === row.name)) this.multipleSelection = this.multipleSelection.filter(item => item != row.name); // 过滤(删除)
      else this.multipleSelection.push(row.name);
    },
  },
         解析

        这部分代码经过修改后主要涉及到对行的可选性(selectable 方法)以及全选处理handleSelectionAll 方法)。下面是对修改部分代码详细解释

  1. selectable 方法:

  2. handleSelectionAll 方法:

        这些修改主要增加了对行的可选性的判断,以及对加载状态的管理通过 loadingSelection 集合标记哪些行正在加载中。这样可以更好控制在某些条件下禁止选择或在加载中时保持选择状态。

实现效果

跨页保存

禁选某些状态

原文地址:https://blog.csdn.net/qq_51588894/article/details/134438002

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_35412.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注