vue2.x,el-table,树形表格存在多选的时候,如何优化让父子选框进行联动?

需求1,当点击多选的时候,不止选中父级,父级下的子项也需要选中
image.png

父子间的选框,类似全选框一样,可以呈现 indeterminate 状态
image.png

同时点击父级选框,可以对子项进行全选/全不选
更改子级选框,也能联动改变父级选框的状态

并且以上联动效果支持在翻页的时候保留

应该如何实现?

阅读 2.1k
avatarAI BotBETA

首先,你需要在父子关系的表格数据中增加一个字段,表示父级和子级之间的关系。然后,你可以使用递归组件来处理父子级选框的联动。

以下是一个基本的实现思路:

  1. 在数据中增加一个字段,表示父级和子级之间的关系。例如,你可以在每个数据项中增加一个 children 字段,该字段是一个数组,存储了该项的所有子级数据项。
  2. 创建一个递归组件,用于渲染表格的每一行。在该组件中,你需要根据当前行数据是否包含子级数据,来决定是否渲染子级表格。同时,你还需要根据当前行的选中状态,来决定是否选中子级表格的所有行。
  3. 在父级表格的行上绑定一个点击事件,当点击时,你需要遍历该行的所有子级数据,将它们的选中状态设置为与父级行相同。同时,如果所有子级行都被选中,则父级行也应该是选中的;否则,父级行应该是未选中的。
  4. 在子级表格的行上绑定一个点击事件,当点击时,你需要将父级行的选中状态设置为与子级行相同。

以下是一个简单的示例代码:

<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="日期" width="180"></el-table-column>
    <el-table-column prop="name" label="姓名" width="180"></el-table-column>
    <el-table-column prop="address" label="地址"></el-table-column>
    <template slot-scope="scope">
      <div @click="handleRowClick(scope.$index)">
        <input type="checkbox" :checked="scope.row.selected">
      </div>
      <el-table v-if="scope.row.children" :data="scope.row.children" style="width: 100%">
        <template slot-scope="scope">
          <div @click="handleChildRowClick(scope.$index, scope.row)">
            <input type="checkbox" :checked="scope.row.selected">
          </div>
        </template>
      </el-table>
    </template>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        { date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄', children: [{ date: '2016-05-03', name: '王小明', address: '上海市普陀区金沙江路 1517 弄', selected: false }, { date: '2016-05-04', name: '王小红', address: '上海市普陀区金沙江路 1519 弄', selected: false }] },
        { date: '2016-05-05', name: '王小虎', address: '上海市普陀区金沙江路 1520 弄', children: [{ date: '2016-05-06', name: '王小明', address: '上海市普陀区金沙江路 1521 弄', selected: false }, { date: '2016-05-07', name: '王小红', address: '上海市普陀区金沙江路 1522 弄', selected: false }] }
      ]
    }
  },
  methods: {
    handleRowClick(index) {
      const row = this.tableData[index]
      if (row.children) {
        row.children.forEach(child => child.selected = row.selected)
      }
    },
    handleChildRowClick(childIndex, childRow) {
      const parentRow = this.$parent.$parent.$index // get parent row index from grandparent scope
      const parentRowChildren = this.tableData[parentRow].children // get parent row children from parent scope
      parentRowChildren[childIndex].selected = childRow.selected // update the selected state of the clicked child row and the others are inverse selected state of clicked one 
1 个回答

https://codesandbox.io/p/sandbox/agitated-merkle-qmhmck?file=...

看看这是不是你想要的,如果是的话,按照下面步骤来:

  1. 给你的el-table加上row-key属性,row-key的值为你的数据唯一标示名,一般会是id
  2. 给你的勾选框column加上reserve-selection属性,不用写值。
  3. 切换分页验证效果。
<template>
  <div id="app">
    <el-table
      ref="multipleTable"
      :data="tableData"
      tooltip-effect="dark"
      row-key="id"
      style="width: 100%"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" reserve-selection width="55">
      </el-table-column>
      <el-table-column label="日期" width="120">
        <template slot-scope="scope">{{ scope.row.date }}</template>
      </el-table-column>
      <el-table-column prop="name" label="姓名" width="120"> </el-table-column>
      <el-table-column prop="address" label="地址" show-overflow-tooltip>
      </el-table-column>
    </el-table>
    <div style="margin-top: 20px">
      <el-button @click="setPage(1)">第一页</el-button>
      <el-button @click="setPage(2)">第二页</el-button>
    </div>
  </div>
</template>

<script>
const fetchData = (page) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      const page1Data = [
        {
          id: "1",
          date: "2016-05-03",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
        },
        {
          id: "2",
          date: "2016-05-02",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
        },
      ];
      const page2Data = [
        {
          id: "3",
          date: "2016-05-03",
          name: "雷军",
          address: "上海市普陀区金沙江路 1518 弄",
        },
        {
          id: "4",
          date: "2016-05-02",
          name: "雷军",
          address: "上海市普陀区金沙江路 1518 弄",
        },
      ];

      if (page === 1) {
        resolve(page1Data);
      }
      if (page === 2) {
        resolve(page2Data);
      }
    }, 1000);
  });
};

export default {
  name: "App",
  data() {
    return {
      page: 1,
      tableData: [],
      multipleSelection: [],
    };
  },

  methods: {
    setPage(page) {
      this.page = page;
    },
    async getTableData(page) {
      const data = await fetchData(page);
      this.tableData = data;
    },
    handleSelectionChange(val) {
      console.log("val", val);
    },
  },
  watch: {
    page: {
      immediate: true,
      handler(val) {
        this.getTableData(val);
      },
    },
  },
};
</script>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题