需求:不管是页面切换还是通过搜索获取数据,都要保持已选中的行保持勾选状态,同时将选中行的内容以标签的形式显示出来,当点击关闭标签时可以对应取消选中状态,点击行中的任意位置也可以切换选中状态,单独勾选复选框一样可以达到要求。

由于需求相对还是蛮复杂的,直接使用row-key和reserve-selection,难以实现。所以直接通过书写代码来控制表格的勾选状态。

注意:我使用的是vue3 + ts!!!!

1. 第一步:书写html代码

给el-table添加对应勾选的监听事件,row-click用于监听鼠标选中某行时的勾选事件(不需要可去掉,我的需求是鼠标选中某行也要勾选);selection-change用于监听鼠标点击某行前面的勾选框、选中某行实现的勾选、表格左上角的全选,三种状态的事件;select用于监听框勾选数据行的 Checkbox 时触发的事件;select-all用于监听鼠标点击表格左上角的全选框。

<!-- 已选择点检项 -->
<el-row
  align="middle"
  class="selected"
  justify="space-between"
  type="flex"
>
  <el-col :span="24">
    <span>已选择:</span>
    <template v-if="selectedCheckOptions">
      <el-tag
        v-for="(item, i) in selectedCheckOptions"
        :key="i"
        closable
        :disable-transitions="false"
        @close="handleCloseTag(item, i)"
      >
        {{ item }}
      </el-tag>
    </template>
  </el-col>
</el-row>
<!-- 表格部分 -->
<el-table
  ref="multipleTableRef"
  :data="gridData"
  :header-cell-style="{
    'background-color': '#fafafa',
    color: '#000',
  }"
  size="small"
  style="width: 100%"
  @row-click="handleClickTableRow"
  @select="onTableSelect"
  @select-all="selectSingleTableAll"
  @selection-change="handleChange"
>
  <el-table-column type="selection" width="50" />
  <el-table-column fixed label="序号" type="index" width="60" />
  <el-table-column label="点检项" prop="itemName" />
  <el-table-column label="分类" prop="itemTypeName" />
</el-table>
<!-- 分页 -->
<div class="page">
  <el-pagination
    v-model:currentPage="currentPage"
    layout="total, prev, pager, next"
    small
    :total="total"
    @current-change="handleCurrentChange"
  />
</div>

2. 所需数据

// 只将表格中设计到需求的重要数据进行展示
const modelInfo = reactive({
  // 当前所在页面的表格数据
  gridData: [],
  // 添加点检项表格全部数据
  tableData: [],
  tableAllSelectedId: [] as any, // 保存表格勾选的全部id
  tableAllSelectedRow: [] as any, // 保存表格勾选的行数据
  selectedCheckOptions: [] as any, // 已选择的点检项
})

// 获取已选择的点检项
modelInfo.selectedCheckOptions = computed(() => {
  return modelInfo.tableAllSelectedRow.map((r: any) => r.itemName)
})

3.所需方法

 (1)从后台获取表格的分页数据的方法

// 获取表格数据的方法 (这里根据后端给的接口进行获取即可)
const getCheckItemData = () => {
  checkItemList({
    itemName: formInline.checkOption,
    itemTypeId: formInline.itemTypeId[formInline.itemTypeId.length - 1],
    filter: [],
    paging: {
      dir: 'DESC',
      limit: modelInfo.pageSize,
      page: modelInfo.currentPage,
      sort: 'createTime',
      start: 0,
    },
  }).then((res: any) => {
    modelInfo.gridData = res.data.records
    // 条数必须是数字才可以显示在分页控件中
    modelInfo.total = parseInt(res.data.total)
    // 关键代码(实现已勾选行数据保持选中状态)
    nextTick(() => {
      modelInfo.gridData.forEach((item: any) => {
        if (modelInfo.tableAllSelectedId.indexOf(item.itemId) > -1) {
          multipleTableRef.value?.toggleRowSelection(item, true)
        } else {
          multipleTableRef.value?.toggleRowSelection(item, false)
        }
      })
    })
  })
}

(2)当选择项发生变化时触发的方法

// 当选择项发生变化时会触发该事件
const handleChange = (val: any) => {
  // 将获取到的id存入tableAllSelectedId数组中
  val.forEach((item: any) => {
    if (modelInfo.tableAllSelectedId.indexOf(item.itemId) === -1) {
      modelInfo.tableAllSelectedId.push(item.itemId)
      modelInfo.tableAllSelectedRow.push(item)
    }
  })
}

(3)点击表格某一行的方法

// 点击表格某一行的方法
const handleClickTableRow = (row: any) => {
// 判断当前行是否已选中
  if (
    findIndexInObejctArr(
      JSON.parse(JSON.stringify(modelInfo.tableAllSelectedRow)),
      row,
      'itemId'
    ) > -1
  ) {
    const index = modelInfo.tableAllSelectedId.indexOf(row.itemId)
    modelInfo.tableAllSelectedId.splice(index, 1)
    modelInfo.tableAllSelectedRow.splice(index, 1)
    nextTick(() => {
      modelInfo.gridData.forEach((item: any) => {
        if (modelInfo.tableAllSelectedId.indexOf(item.itemId) > -1) {
          multipleTableRef.value?.toggleRowSelection(item, true)
        } else {
          multipleTableRef.value?.toggleRowSelection(item, false)
        }
      })
    })
  } else {
    multipleTableRef.value?.setCurrentRow(row)
    multipleTableRef.value!.toggleRowSelection(row, true)
  }
}

(4)勾选数据行的 Checkbox 时触发的方法

// 勾选数据行的 Checkbox 时触发的方法
const onTableSelect = (rows: any, row: any) => {
  //  判断是点击了表格勾选还是取消勾选,true为选中,0或false是取消选中
  const selected = rows.length && rows.indexOf(row) !== -1
  if (!selected) {
    // 如果点击取消勾选
    const index = modelInfo.tableAllSelectedId.indexOf(row.itemId)
    modelInfo.tableAllSelectedId.splice(index, 1) // 取消勾选,则删除id
    modelInfo.tableAllSelectedRow.splice(index, 1) // 取消勾选,则删除数据
  }
}

(5)表格全选触发的方法

// 表格全选触发的方法
const selectSingleTableAll = (selection: any) => {
  // 获取当前页码所显示的数据
  const a: any = modelInfo.gridData
  // 获取当前页勾选的数据
  const b = selection
  let flag_inCurrentPage
  selection.forEach((item: any) => {
    if (item.itemId === a[0].itemId) {
      flag_inCurrentPage = true
      return
    }
  })
  const flag = a.length === b.length && flag_inCurrentPage
  if (flag) {
    // 切换成了全选状态
    modelInfo.gridData.forEach((r: any) => {
      if (modelInfo.tableAllSelectedId.indexOf(r.itemId) === -1) {
        modelInfo.tableAllSelectedId.push(r.itemId) // 如果点击全选就保存全部id
        modelInfo.tableAllSelectedRow.push(r) //如果点击全选就保存全部数据
      }
    })
  } else {
    // 切换成了非全选状态
    modelInfo.tableAllSelectedId = []
    modelInfo.tableAllSelectedRow = []
  }
}

(6)查找对象在对象数组中位置的方法

// 查找对象在对象数组中的位置
findIndexInObejctArr: function(arr, obj) {
  for (let i = 0, iLen = arr.length; i < iLen; i++) {
    if (arr[i].deliverId === obj.deliverId) {
       return i
    }
  }
  return -1
}

(7)删除标签的方法

// 删除标签的方法
const handleCloseTag = (tag: string, index: number) => {
  // 先删除保存表格勾选的全部行数据中对应的数据,以及保存表格勾选的全部行id中对应的数据
  modelInfo.tableAllSelectedId.splice(index, 1)
  modelInfo.tableAllSelectedRow.splice(index, 1)
  // 再根据已勾选的全部id来将对应行选中
  nextTick(() => {
    modelInfo.gridData.forEach((item: any) => {
      if (modelInfo.tableAllSelectedId.indexOf(item.itemId) > -1) {
        multipleTableRef.value?.toggleRowSelection(item, true)
      } else {
        multipleTableRef.value?.toggleRowSelection(item, false)
      }
    })
  })
}

(8)切换页码的方法

const handleCurrentChange = (val: number) => { 
   modelInfo.currentPage = val
   getCheckItemData()
}

(9)查询方法

// 搜索方法
const onSearch = () => {
  modelInfo.currentPage = 1
  getCheckItemData()
}

(10)确认添加的方法(由于我的表格是出现在弹出层中的,故增加了此方法,该方法和本文章的需求无关,可以直接忽视)

// 确认添加点检项的方法
const confirmAdd = () => {
  modelInfo.checkOptions = modelInfo.tableAllSelectedRow
  dialogAddVisible.value = false
  // 清除搜索内容
  formInline.checkOption = ''
  formInline.itemTypeId = []
  modelInfo.currentPage = 1
  getCheckItemData()
}

4.效果图

 (1)选中的会在上面同步显示

 

(2)跨行也能保留选中状态和标签

 

(3)搜索也一样能保留选中状态

借鉴:elementui el-table表格实现跨页(翻页)保存勾选状态(后端分页)_公孙元二的博客-CSDN博客_el-table跨页勾选 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐