el-tree-select 选中默认展示全部层级

一、效果预览

代码地址

最终效果

二、版本说明

Vue:v3
Element Plus:v2.4.1

三、实现

1. 思路
  • 当点击最后一层节点的时候,根据该节点的 Node Tree ,循环找到每一层的节点信息,进行 label 字段拼接,拼接完成后将其赋给绑定的值,并存储一份拼接的 label 字段和当前选中节点的 key 备用;
  • 当再次进行选择时,手动将存储的 key 赋给绑定的值,使其能够高亮显示已选中的节点;
  • 核心是操作 tree 组件的 【node-click】和 select 组件的【visible-change】方法;
2. html部分
<template>
  <el-tree-select
    v-model="selectVal"
    style="width: 100%"
    clearable
    :data="data"
    :render-after-expand="false"
    @node-click="handleNodeClickEvent"
    @visible-change="handleVisibleChangeEvent"
  />
</template>
3. 核心实现
  • 初始化两个字段,进行缓存:
// 缓存当前选中节点的key
const cacheNodeKey = ref("");
// 缓存拼接后的文本
const cacheJoinLabel = ref("");
  • 当点击节点时:
// 节点节点事件
const handleNodeClickEvent = (_: Tree, node: Node) => {
  const { level, key, childNodes } = node;

  // 只有点击最后一级节点时,才继续后续操作
  if (childNodes.length > 0) return;

  // 缓存当前节点的key
  cacheNodeKey.value = key as string;

  // 记录当前选中的节点信息
  let cacheNode = node;

  // 循环 node tree,将其放在 nodeList 里
  const nodeList = [];
  for (let i = level; i >= 1; i--) {
    nodeList.unshift(cacheNode);
    cacheNode = cacheNode.parent;
  }

  if (nodeList.length === 0) return;

  // 数据拼接
  const labelText = nodeList.reduce((pre, cur) => {
    return (pre += ` - ${cur.label}`);
  }, "");

  // 处理拼接后的多余字符
  cacheJoinLabel.value = labelText.slice(3);

  // 一定要在 nextTick 方法中进行赋值操作
  nextTick(() => {
    selectVal.value = unref(cacheJoinLabel);
  });
};
  • 当下拉框出现或隐藏时
// 下拉框出现或隐藏
const handleVisibleChangeEvent = (visible: boolean) => {
  if (visible) {
    // 如果是打开,将缓存的key赋给绑定值
    nextTick(() => {
      selectVal.value = unref(cacheNodeKey);
    });
  } else {
    // 如果是关闭,将缓存的label赋给绑定值
    nextTick(() => {
      selectVal.value = unref(cacheJoinLabel);
    });
  }
};

四、完成代码

<template>
  <el-tree-select
    v-model="selectVal"
    style="width: 500px"
    clearable
    :data="data"
    :render-after-expand="false"
    @node-click="handleNodeClickEvent"
    @visible-change="handleVisibleChangeEvent"
  />
</template>

<script lang="ts" setup name="ExpandSelect">
import { ref } from "vue";

import type Node from "element-plus/es/components/tree/src/model/node";

const selectVal = ref();

const data = [
  {
    value: "1",
    label: "🌞太阳科技公司",
    children: [
      {
        value: "10",
        label: "云技术事业部",
        children: [
          {
            value: "100",
            label: "王老五",
          },
        ],
      },
    ],
  },
  {
    value: "2",
    label: "🌍地球生物公司",
    children: [
      {
        value: "11",
        label: "市场营销部",
        children: [
          {
            value: "101",
            label: "宋老五",
          },
        ],
      },
      {
        value: "12",
        label: "科研部",
        children: [
          {
            value: "102",
            label: "宋老六",
          },
        ],
      },
    ],
  },
  {
    value: "3",
    label: "🌕月球金融公司",
    children: [
      {
        value: "13",
        label: "放贷部",
        children: [
          {
            value: "103",
            label: "吴老二",
          },
        ],
      },
      {
        value: "14",
        label: "催收部",
        children: [
          {
            value: "104",
            label: "吴老三",
          },
        ],
      },
    ],
  },
];

interface Tree {
  label: string;
  children?: Tree[];
}

// 缓存当前选中节点的key
const cacheNodeKey = ref("");
// 缓存拼接后的文本
const cacheJoinLabel = ref("");

// 节点节点事件
const handleNodeClickEvent = (_: Tree, node: Node) => {
  const { level, key, childNodes } = node;

  // 只有点击最后一级节点时,才继续
  if (childNodes.length > 0) return;

  // 缓存当前节点的key
  cacheNodeKey.value = key as string;

  // 记录当前选中的节点信息
  let cacheNode = node;

  // 循环 node tree,将其放在 nodeList 里
  const nodeList = [];
  for (let i = level; i >= 1; i--) {
    nodeList.unshift(cacheNode);
    cacheNode = cacheNode.parent;
  }

  if (nodeList.length === 0) return;

  // 数据拼接
  const labelText = nodeList.reduce((pre, cur) => {
    return (pre += ` - ${cur.label}`);
  }, "");

  // 处理拼接后的多余字符
  cacheJoinLabel.value = labelText.slice(3);

  // 一定要在 nextTick 方法中进行赋值操作
  nextTick(() => {
    selectVal.value = unref(cacheJoinLabel);
  });
};

// 下拉框出现或隐藏
const handleVisibleChangeEvent = (visible: boolean) => {
  if (visible) {
    // 如果是打开,将缓存的key赋给绑定值
    nextTick(() => {
      selectVal.value = unref(cacheNodeKey);
    });
  } else {
    // 如果是关闭,将缓存的label赋给绑定值
    nextTick(() => {
      selectVal.value = unref(cacheJoinLabel);
    });
  }
};
</script>
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值