Vue3 + TypeScript + Element Plus 表格行多选与行展开的组合应用实例

场景应用效果:

需求特点:

1、表格行未选中状态,点击表格行(或点击行内的复选框),选中行,展开行 ;

2、表格行已选中状态,点击表格行(或点击行内的复选框),取消选中行,取消展开行 ;

3、展开行后,表格滚动条设置到当前选中行的位置;

代码特点:

表格设置展开行的关键信息 row-key 和 expand-row-keys

row-key="id"

:expand-row-keys="expandedRows"

:default-expand-all="false"

展开行 type="expand",width="1" 故意屏蔽列,只能设置最小为1,设置0是自适应列宽,再配合样式设置,隐藏默认的展开图标

:deep(.el-table__expand-icon) {

display: none;

}

选择行 type="selection"

点击表格行事件 @row-click="onTableRowClick"

表格选集变化事件 @selection-change="handleTableSelectionChange"

监听表格选集变化 watch

表格滚动条设置到当前选中行的位置 await nextTick(); tableRef.value?.setScrollTop(topVal);

实例代码:

ReagentInDialog.vue

TypeScript 复制代码
<script setup lang="ts" name="ReagentInDialog">
......
// 表格数据
const tableData = ref<IReagentInByCkDetail[]>([]);
// 表格选集
const tableSelection = ref<IReagentInByCkDetail[]>([]);
// 表格加载标识
const tableLoading = ref(false);
// 表格实例对象
const tableRef = ref<TableInstance>();

// 点击表格的行,实现多选
const onTableRowClick = async (row: IReagentInByCkDetail) => {
  // 如果点击的当前行在表格选集中,那么取消选中行,否则选中行
  if (tableSelection.value.includes(row)) {
    // 取消选中行
    tableRef.value?.toggleRowSelection(row, false);
  } else {
    // 选中行
    tableRef.value?.toggleRowSelection(row, true);
  }

  // 等待 DOM 渲染完毕
  await nextTick();

  let rowIndex = tableData.value.findIndex((item) => item.id === row.id);
  let topVal = 0;
  for (let i = 0; i < rowIndex; i++) {
    topVal += tableSelection.value.includes(tableData.value[i]) ? 50 + 130 : 50;
  }
  // 表格滚动条设置到当前选中行的位置
  tableRef.value?.setScrollTop(topVal);
};

// 获取表格选集
const handleTableSelectionChange = (selection: IReagentInByCkDetail[]) => {
  tableSelection.value = selection;
};

// 监听表格选集变化
watch(tableSelection, () => {
  // 展开行
  expandedRows.value = tableSelection.value.map((item) => item.id.toString());
});

......
</script>

<template>
......

          <el-table
            ref="tableRef"
            :data="tableData"
            v-loading="tableLoading"
            :border="false"
            highlight-current-row
            stripe
            :select-on-indeterminate="false"
            row-key="id"
            :expand-row-keys="expandedRows"
            :default-expand-all="false"
            style="width: 100%; height: 100%"
            @row-click="onTableRowClick"
            @selection-change="handleTableSelectionChange">
            <!-- 展开列 -->
            <el-table-column type="expand" width="1">
              <!-- 展开行的内容 -->
              <template #default="scope">
                <el-form :model="scope.row" label-width="auto" style="margin: 8px 16px">
                  <el-row :gutter="10">
                    <el-col :span="12">
                      <el-form-item label="试剂名称" label-position="right">
                        <el-input v-model="scope.row.reagentName" />
                      </el-form-item>
                    </el-col>
                    <el-col :span="12">
                      <el-form-item label="试剂编号" label-position="right">
                        <el-input v-model="scope.row.reagentNo" />
                      </el-form-item>
                    </el-col>
                  </el-row>

                  ......

                </el-form>
              </template>
            </el-table-column>
            <!-- 选择列 -->
            <el-table-column type="selection" width="30" />

            ......
            <!-- 操作列 -->
            <el-table-column label="操作" header-align="center" align="center" fixed="right" width="60">
              <template #default="scope">
                <!-- 点击时使用 .stop 修饰符阻止事件冒泡,只会执行@click的事件逻辑,其他事件不会触发,如 @row-click="onTableRowClick" -->
                <el-button type="danger" size="default" text @click.stop="onDelClick(scope.row.id)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>

......
</template>

<style scoped lang="scss">
......

/* 隐藏默认的展开图标 */
:deep(.el-table__expand-icon) {
  display: none;
}

......
</style>