tree回显问题

问题描述:

1、el-tree 勾选反显,原本整个父子节点都勾选状态,新增一个子节点,因为父节点是全选状态,所以新增的子节点也呈勾选状态,实际是未勾选状态。

2、用的是default-checked-keys 回显

数据更新后,必须在 $nextTick 中调用 setCheckedKeys,这样才能确保树组件正确回显勾选状态。

解决思路:

问题 原因 解决方案
回显不生效 default-checked-keys 非响应式 使用 setCheckedKeys
设置时机不对 DOM 未渲染完成 包裹在 $nextTick
传了父节点 id 父节点会强制全选,并级联勾选所有子节点 只传叶子节点 id 给 setCheckedKeys
  • 核心逻辑
  • 先处理子节点,再根据子节点状态回推父节点
  • 只传叶子节点 id 给 setCheckedKeys,父节点状态由组件自动计算
  • markTreeChecked 返回的是树数据本身,不会影响 setCheckedKeys 的行为
    这样即使后端返回的数据中新增了子节点,父节点也能正确呈现半选状态。

html

javascript 复制代码
<el-tree
	:data="list"
	show-checkbox
	node-key="id"
	ref="tree"
	default-expand-all
	:props="{label: 'name',value: 'id'}"
></el-tree>

获取数据及回显调用(created 或 mounted)

javascript 复制代码
// 获取树的数据
getMenuTree()
  .then(res => {
    this.list = res.data.data;
    // 获取已勾选的数据id
    return getEchoData();
  })
  .then(res => {
    // 处理回显
    let menuIds = [];
    if (res.data.data.menuIds && res.data.data.menuIds.length > 0) {
      menuIds = res.data.data.menuIds.split(',');
    }
    
    // 根据返回的 menuIds 处理树数据,标记每个节点的选中状态(用于界面展示)
    this.markTreeChecked(this.list, menuIds);
    
    this.$nextTick(() => {
      if (this.$refs.tree) {
        // 只传叶子节点 id,避免父节点强制全选
        const leafIds = this.filterLeafIds(this.list);
        this.$refs.tree.setCheckedKeys(leafIds);
      }
    });
  });

methods

javascript 复制代码
// 递归标记树节点的选中状态
markTreeChecked(treeData, checkedIds) {
  treeData.forEach(node => {
    if (node.children && node.children.length > 0) {
      // 先处理子节点
      const childCheckedCount = this.markTreeChecked(node.children, checkedIds);
      
      // 根据子节点选中数量,计算当前父节点状态
      const allChecked = childCheckedCount === node.children.length;
      const noneChecked = childCheckedCount === 0;
      
      node.checked = allChecked;
      node.halfChecked = !allChecked && !noneChecked;
    } else {
      // 叶子节点:直接判断是否在选中列表中
      node.checked = checkedIds.includes(node.id);
    }
  });
}

// 收集所有选中的叶子节点 id
filterLeafIds(treeData) {
  const leafIds = [];
  
  const traverse = (nodes) => {
    nodes.forEach(node => {
      if (node.children && node.children.length > 0) {
        traverse(node.children);
      } else if (node.checked) {
        leafIds.push(node.id);
      }
    });
  };
  
  traverse(treeData);
  return leafIds;
}
相关推荐
weixin_BYSJ19871 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
qetfw2 小时前
MWU:Vue 3 + FastAPI 的 MaaFramework 跨平台 WebUI 源码
前端·vue.js·python·fastapi·开源项目·效率工具
mfxcyh2 小时前
Vue3+Ant Design Vue 实现手动异步文件上传(含大小校验、弹窗上传)
前端·javascript·vue.js
meilindehuzi_a2 小时前
Vue3进阶基础:指令修饰符、v-model表单绑定、动态样式、计算属性与侦听器实战
前端·javascript·vue.js
csdn2015_2 小时前
vue 前端运行命令
前端·javascript·vue.js
Cobyte3 小时前
根据浏览器解析 HTML 的规范实现 HTML 解析器
前端·javascript·vue.js
用户83134859306983 小时前
Cesium 实现行政区反向遮罩镂空效果(自定义暗色蒙层+矢量/影像底图切换)
vue.js·webgl·cesium
默_笙3 小时前
😁 LLM 不知道的事它不会说"不知道",而是会"编"——RAG 就是让它闭嘴先查资料
前端·javascript
Revolution613 小时前
变量提升到底提升了什么:为什么 var 是 undefined,let 却直接报错
前端·javascript