You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue树形组件如何实现点击项切换颜色并重置上一项颜色

问题原因

你现在的实现里每个递归渲染的TreeView组件实例都是独立维护自身的col颜色状态,实例之间没有统一的状态同步机制,点击新节点时无法通知旧的选中节点重置颜色,自然实现不了互斥选中的效果。

修复方案

不用手动查找上一个选中节点改样式,利用Vue响应式特性,把选中状态提升为所有树节点共享的响应式状态,每个节点根据「当前节点ID是否等于全局选中ID」来判断自身背景色即可,步骤如下:

  • 给组件加依赖注入配置,让所有递归生成的树节点共享同一个选中状态对象,不用逐层传参
  • 把原来绑定内部col变量的背景色样式,改成对比共享选中ID的动态判断
  • 修正点击事件的传参问题,加事件冒泡阻止,避免点子节点误触发父节点逻辑
完整修正代码

组件脚本部分

export default {
  name: 'TreeView', // 递归组件必须设置name字段
  props: {
    tree: {
      type: Object,
      required: true
    },
    depth: {
      type: Number,
      default: 0
    }
  },
  // 注入父级传递的共享选中状态
  inject: {
    treeSelection: {
      default: null
    }
  },
  data() {
    return {
      isOpen: false,
      // 根节点初始化共享选中状态
      innerSelection: {
        activeId: null
      }
    }
  },
  // 向所有子节点传递共享选中状态
  provide() {
    return {
      treeSelection: this.treeSelection || this.innerSelection
    }
  },
  computed: {
    isFolder() {
      return this.tree.children && this.tree.children.length
    }
  },
  methods: {
    toggle(e) {
      if (!this.isFolder) return
      this.isOpen = !this.isOpen
    },
    getEl(e) {
      // 阻止事件冒泡,避免触发父节点点击逻辑
      e.stopPropagation()
      // 更新共享的选中节点ID,所有节点自动同步样式
      this.treeSelection.activeId = this.tree.id
      return this.tree.id
    }
  }
}

模板部分

<template>
  <li 
    class="main__li list" 
    :style="{
      'margin-left': `${depth * 20}px`,
      'background-color': treeSelection.activeId === tree.id ? 'blue' : 'initial'
    }" 
    @click="toggle($event); getEl($event)" 
    :title="tree.name"
  >
    {{ tree.name }}
  </li>
  <ul v-show="isOpen" v-if="isFolder" class="ul__ctg list">
    <TreeView 
      v-for="(chld, inx) in tree.children"
      :key="inx"
      :tree="chld" 
      :depth="depth + 1"
    />
  </ul>
</template>
逻辑说明
  • 所有递归渲染的树节点共享同一个响应式的treeSelection对象,不管点击哪一层的节点,只要修改activeId为当前节点ID,所有节点都会自动重新计算背景色:ID匹配的显示蓝色,不匹配的回到默认初始色,完全不需要手动操作DOM查找旧节点重置样式。
  • 加了e.stopPropagation()是为了避免点击子节点时,事件冒泡到父级li触发父节点的选中逻辑,导致选中状态错乱。
  • 修正了原来模板里toggle(e)的写法错误,模板里要取事件对象必须显式写$event传参,否则会报e is not defined的错误。
  • 递归组件必须显式设置name字段,否则组件内部调用自身会找不到组件定义。

内容的提问来源于stack exchange,提问作者Netervey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:34:46