解决vxe-table树形表格父节点和子节点不会联动选中取消问题

文章介绍了在使用vxe-table时遇到的树形表格父节点和子节点复选框不联动的问题。通过设置`checkField`属性并确保行数据包含该字段,可以实现父节点选中或取消时子节点的同步状态。数据结构需包含id和parentId来定义层级关系,而vxe-table的配置包括children、expandAll、reserve等选项。解决方法简单有效,适用于处理类似问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解决vxe-table树形表格父节点和子节点不会联动选中取消问题

vxe-table数据结构

在这里插入图片描述
vxe-table接收的数据结构是一维数据,主要利用id和parentId来确定层级关系。
但是平常接口返回的数据结构是个多层数组嵌套的结构。
[ id:1,chidlren:[ { id:2,parentId:1 }, {id:3,parentId:1}] ]

vxe-table树形复选框

<vxe-table
    row-id="id"
    :tree-config="{
      children: 'children',
      expandAll: true,
      reserve: true,
      rowField: 'id',
      parentField: 'parentId',
      transform: false,
    }"
    :data="dataTree"
    ref="xTable"
    :row-config="{
      keyField: 'menuId',
    }"
    :checkbox-config="{
      checkRowKeys: checkRowKeys,
      labelField: 'menuName'
    }"
    resizable
  >
    <vxe-column
      type="checkbox"
      title="title"
      tree-node
      indeterminate
    ></vxe-column>
</vxe-table>

这样写完会出现一个问题,就是父节点选中和取消之后,子节点并没有选中和取消。
在这里插入图片描述

解决方法

在 **:checkbox-config=“{ }”**增加一个checkField属性,绑定选中属性,如果设置了该属性渲染速度更快,行数据中必须存在该字段,否则无效。

<vxe-table
    row-id="id"
    :tree-config="{
      children: 'children',
      expandAll: true,
      reserve: true,
      rowField: 'id',
      parentField: 'parentId',
      transform: false,
    }"
    :data="dataTree"
    ref="xTable"
    :row-config="{
      keyField: 'id',
    }"
    :checkbox-config="{
      checkRowKeys: checkRowKeys,
      labelField: 'name'
      checkField: 'checked'
    }"
    resizable
  ></vxe-table>

就可以解决父节点选中和取消之后,子节点并没有选中和取消的问题。

vxe-table相关

vxe-table官方文档:https://vxetable.cn/#/table/api

我的tableListselected都是两层结构,为什么checkSelectedTree这个方法里,走到了if (props.isTree)了,但是为什么子节点没有选中父节点是半选状态<template> <div> <el-dialog :close-on-click-modal="false" :close-on-press-escape="false" @close="handleCancel" v-model="dialogVisible"> <template #header> <span>添加国家/地区 </span> </template> <div class="container"> <div class="search-row"> <el-input v-model="keyword" @keydown.enter="handleSearch" clearable placeholder="请输入国家/地区"></el-input> <el-button type="primary" style="margin-left: 10px" @click="handleSearch" >搜索</el-button > <el-button @click="handleReset">重置</el-button> </div> <vxe-table max-height="400px" round v-loading="isLoading" ref="tableRef" :data="tableList" :checkbox-config="{ reserve: true, checkStrictly: false }" @checkbox-change="selectChangeEvent" v-bind="tableConfig"> <vxe-column type="checkbox" title="国家/地区" :tree-node="isTree"> <template #default="{ row }"> {{ row.name }}{{ row.cn_name ? '/' + row.cn_name : '' }} </template> </vxe-column> </vxe-table> </div> <template #footer> <el-button @click="handleCancel">取消</el-button> <el-button type="primary" @click="handleSuccess">保存</el-button> </template> </el-dialog> </div> </template> <script setup lang="tsx"> import { ref, defineProps, defineEmits, onMounted, watch, computed, nextTick } from 'vue' import { listCountry } from '@/pc/src/api/logistics' const props = defineProps({ visible: { type: Boolean, default: false }, selected: { type: Array as any, default: () => [] }, selectedBy: { type: String, default: 'id' }, isTree: { type: Boolean, default: false } }) const tableConfig = computed(() => { if (props.isTree) { return { 'tree-config': { rowField: 'id', parentField: 'pid' } } } return {} }) const isLoading = ref(false) const tableList = ref<any[]>([]) const tableRef = ref() // 根据props.selected传进来的树结构递归勾选 const checkSelectedTree = (selectedTree: any[]) => { const $table = tableRef.value if (!$table) return selectedTree.forEach((selNode) => { // 如果有子节点,递归勾选 if (selNode.children?.length) { checkSelectedTree(selNode.children) return } // 勾选当前节点 let row if (props.isTree) { const parentIndex = tableList.value.findIndex((t) => t.id === selNode.pid) row = tableList.value[parentIndex]?.children?.find((t) => t.id === selNode.area_id) console.log(row) } else { row = tableList.value.find((t) => t.value === selNode.value) } if (row) { $table.setCheckboxRow(row, true) } }) } // 初始化默认勾选 const initDefaultSelection = async () => { if (!props.selected?.length) return checkSelectedTree(props.selected) } const getCountry = async () => { isLoading.value = true const res = await listCountry({}) if (res.code === 200 && res.data) { tableList.value = res.data await nextTick() initDefaultSelection() // 数据重新加载后勾选 } isLoading.value = false } // 搜索 const keyword = ref('') const handleSearch = async () => { const res = await listCountry({ name: keyword.value }) if (res.code === 200 && res.data) { tableList.value = res.data await nextTick() initDefaultSelection() } } console.log(props.selected) const selectChangeEvent = ({ checked, row }) => { console.log(checked, row) // 选中 if (checked) { // 如果是一级,全部选中下级 if (+row.pid === 0) { selectedObj.value[row.id] = row } else { // 获取是否之前有选中过的children const pValChildren = selectedObj.value[row.pid]?.children || [] // 获取父节点数据 const pJson = tableList.value.find((t) => t.id === row.pid) // 组装新数据 selectedObj.value[row.pid] = { ...pJson, children: [...pValChildren, row] } } } else { // 取消选中 // 如果是一级,全部取消选中下级 if (+row.pid === 0) { delete selectedObj.value[row.id] } else { const pValChildren = selectedObj.value[row.pid]?.children || [] const newPVal = pValChildren.filter((t) => t.id !== row.id) if (!newPVal.length) { delete selectedObj.value[row.pid] } else { selectedObj.value[row.pid].children = newPVal } } } // records.value = $table.getCheckboxRecords() } // 删除已选国家 const handleDelete = (target) => { // selectList.value = selectList.value.filter((item) => item.id !== target.id) } // 弹出框的显示与隐藏 const dialogVisible = ref<boolean>(props.visible) watch( () => dialogVisible.value, (val) => { emits('update:visible', val) } ) const emits = defineEmits([ 'update:visible', 'updateSelectCountryDialog', 'updateCountryData' ]) // const selectList = ref<any[]>([]) const selectedObj = ref<any>({}) // 重置 const handleReset = () => { keyword.value = '' getCountry() } const handleCancel = () => { dialogVisible.value = false emits('updateSelectCountryDialog', false) } const handleSuccess = () => { // emits('updateCountryData', selectList.value) console.log(selectedObj.value) emits('updateCountryData', selectedObj.value) handleCancel() } onMounted(() => { getCountry() }) </script>
最新发布
07-31
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值