基于el-table实现跨页多选功能

发布于:2025-08-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

功能点

1. 跨页多选
2. 默认勾选项

效果图

在这里插入图片描述

关键点

切换行的选中状态

toggleRowSelection(row, selected)

切换勾选状态后更新默认勾选项数据

在事件@select="handleSelect"中监听取消勾选项

完整代码

<template>
  <div>
    <div class="list-title">
      <div class="line"></div>
      <div class="title1">列表</div>
      <div class="selection-info" v-if="selectedIds.length > 0">
        已选择 {{ selectedIds.length }}<el-button type="text" size="mini" @click="clearAllSelection"
          >清空选择</el-button
        >
      </div>
    </div>

    <!-- 列表搜索区域 -->
    <div class="search-container">
      <el-form :model="queryParams" ref="QueryForm" size="small" v-show="true">
        <el-row :gutter="20" type="flex" justify="space-around" align="bottom">
          <el-col :span="12">
            <el-form-item label="名称" prop="name" label-width="40px">
              <el-input
                v-model="queryParams.name"
                placeholder="请输入名称"
                clearable
                @keyup.enter.native="handleQuery"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item>
              <el-button
                type="primary"
                icon="el-icon-search"
                size="mini"
                @click="handleQuery"
                >搜索</el-button
              >
              <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
                >重置</el-button
              >
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </div>

    <el-table
      ref="tableRef"
      :data="tableData"
      max-height="550"
      v-loading="loading"
      @select="handleSelect"
      @selection-change="selectionChange"
    >
      <el-table-column type="selection" width="55" />
      <el-table-column type="index" label="序号" width="50" align="center" />
      <el-table-column
        v-for="(item, index) in tableCols"
        :key="index"
        :prop="item.prop"
        show-overflow-tooltip
        :label="item.label"
        align="center"
      >
      </el-table-column>
    </el-table>
    <pagination
      v-show="total > 0"
      :total="total"
      small
      :pagerCount="5"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="handlePagination"
    />
  </div>
</template>

<script>
import { listApi } from "@/api/basic/transtation.js";
export default {
  name: "heatExchangeStation",
  props: {
    // 表格默认需要勾选 ids 项
    defaultSelection: {
      type: Array,
      default: () => [],
    },
    dataNum: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      tableCols: [
        {
          prop: "name",
          label: "名称",
        },
        {
          prop: "address",
          label: "地址",
        },
        {
          prop: "heatNetName",
          label: "所属名称",
        },
      ],
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        name: undefined,
      },
      tableData: [],
      total: 0,
      loading: false,
      // 默认勾选项数据源
      defaultSelectedIds: [],
      // 列表所有勾选项数据源
      selectedIds: [],
    };
  },
  watch: {
    defaultSelection(val) {
      this.defaultSelectedIds = val;
    },
  },
  methods: {
    // 获取列表
    getList() {
      this.loading = true;
      listApi({ ...this.queryParams, dataNum: this.dataNum })
        .then((res) => {
          this.tableData = res?.rows || [];
          this.total = res?.total || 0;
          this.$nextTick(() => {
            this.setDefaultSelection();
          });
        })
        .finally(() => {
          this.loading = false;
        });
    },
    handlePagination(newPagination) {
      this.queryParams.pageNum = newPagination.page;
      this.queryParams.pageSize = newPagination.limit;
      this.getList();
    },
    /**
     * 勾选数据行Checkbox时触发的函数--更新默认选中项数据
     * selection { Array } 当前选中的所有行数据数组
     * row { Object }当前操作的行数据
     */
    handleSelect(selection, row) {
      // 判断当前行是否被勾选
      const isSelected = selection.includes(row);
      if (isSelected) {
        // 如果被勾选且不在需要勾选的数据源 selectedIds 中,则添加到数据源中
        if (!this.defaultSelectedIds.includes(row.id)) {
          this.defaultSelectedIds.push(row.id);
        }
      } else {
        // 如果取消勾选,并且可以从从数据源 selectedIds 中获取到,则删除
        const index = this.defaultSelectedIds.indexOf(row.id);
        if (index !== -1) {
          this.defaultSelectedIds.splice(index, 1);
        }
      }
    },
    /**
     * 勾选列表触发的函数
     * selection { Array } 选中的所有行数据
     */
    selectionChange(selection) {
      // 获取当前页所有行ID
      const currentPageIds = this.tableData.map((row) => row.id);
      // 获取当前页已选择ID
      const currentPageSelectedIds = selection.map((row) => row.id);
      // 从全局选择数据ID中过滤掉当前页没有选择的ID
      this.selectedIds = this.selectedIds.filter(
        (id) => !currentPageIds.includes(id)
      );
      // 更新全局勾选ID数据
      this.selectedIds = [...this.selectedIds, ...currentPageSelectedIds];
    },
    // 给列表设置默认勾选项--①获取列表后需要更新;②获取到需要勾选的ID后需要更新
    setDefaultSelection() {
      this.$nextTick(() => {
        // 清空表格所有勾选项
        this.$refs.tableRef?.clearSelection();

        // 设置列表默认选项
        if (this.tableData.length > 0) {
          if (this.defaultSelectedIds?.length > 0) {
            this.tableData.forEach((row) => {
              if (this.defaultSelectedIds.includes(row.id)) {
                this.$refs.tableRef?.toggleRowSelection(row, true);
              }
            });
          }
        }
      });
    },
    // 清空所有选择
    clearAllSelection() {
      this.$refs.tableRef?.clearSelection();
      this.selectedIds = [];
      this.defaultSelectedIds = [];
    },
    // 查询
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    // 重置查询
    resetQuery() {
      this.resetForm("QueryForm");
      this.queryParams.pageSize = 10;
      this.handleQuery();
    },
  },
};
</script>

<style scoped lang="scss">
.selection-info {
  margin-left: auto;
  display: flex;
  align-items: center;
  font-size: 14px;
  color: #409eff;

  .el-button {
    margin-left: 10px;
    color: #f56c6c;
  }
}

::v-deep .el-table__header-wrapper .el-checkbox {
  display: none;
}
</style>