自学内容网 自学内容网

Vue 展示一个带有复选框的树形菜单,并通过按钮收集已选中的节点

 

<template>
  <div>
    <el-tree
      ref="tree"
      :data="menuOptions"
      :props="treeProps"
      node-key="id"
      :default-checked-keys="menuId"
      show-checkbox
      @check="handleCheck"
    >
    </el-tree>
    <button @click="logCheckedNodes">收集已选节点</button>
    <pre>{{ JSON.stringify(checkedNodes, null, 2) }}</pre>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // menuId: [543, 575, 576, 688, 689, 690, 577, 691, 692],
      menuId: [ 688, 689, 690, 691, 692 ],
      menuOptions: [
        { id: 543, label: "首页", business_type: 0 },
        {
          id: 575,
          label: "up评级后台",
          business_type: 0,
          children: [
            {
              id: 576,
              label: "up评级",
              business_type: 0,
              children: [
                { id: 688, label: "导入评级", business_type: 0 },
                { id: 689, label: "评级打分", business_type: 0 },
                { id: 690, label: "分页获取评级", business_type: 0 }
              ]
            },
            {
              id: 577,
              label: "运营复评",
              business_type: 0,
              children: [
                { id: 691, label: "重新评级", business_type: 0 },
                { id: 692, label: "分页获取评级", business_type: 0 }
              ]
            },
            {
              id: 578,
              label: "评级查询",
              business_type: 0,
              children: [
                { id: 693, label: "导出评级明细", business_type: 0 },
                { id: 694, label: "分页获取评级", business_type: 0 },
                { id: 695, label: "导入扶持up", business_type: 0 },
                { id: 696, label: "导入非扶持up", business_type: 0 },
                { id: 697, label: "主播重新评级", business_type: 0 }
              ]
            }
          ]
        }
      ],
      treeProps: {
        label: 'label',
        children: 'children',
        disabled: (data) => this.menuId.includes(data.id)
      },
      checkedNodes: []
    };
  },
  methods: {
    getCheckedNodes(nodes, checkedKeys) {
      return nodes.reduce((acc, node) => {
        if (checkedKeys.includes(node.id) && !this.menuId.includes(node.id)) {
          const newNode = { ...node };
          if (node.children) {
            newNode.children = this.getCheckedNodes(node.children, checkedKeys);
          }
          acc.push(newNode);
        } else if (node.children) {
          const childNodes = this.getCheckedNodes(node.children, checkedKeys);
          if (childNodes.length > 0) {
            const partialNode = { ...node, children: childNodes };
            acc.push(partialNode);
          }
        }
        return acc;
      }, []);
    },
    logCheckedNodes() {
      const checkedKeys = this.$refs.tree.getCheckedKeys(true);
      const checkedNodes = this.getCheckedNodes(this.menuOptions, checkedKeys);
      this.checkedNodes = checkedNodes;
      console.log('Checked Nodes:', checkedNodes);
    }
  }
};
</script>

<style scoped>
/* 样式可以保留 */
</style>

这个代码使用 Vue.js 和 Element UI 的 <el-tree> 组件来展示一个带有复选框的树形菜单,并通过按钮收集已选中的节点。以下是代码的详细解释:

模板部分 (<template>)

<template>
  <div>
    <el-tree
      ref="tree"
      :data="menuOptions"
      :props="treeProps"
      node-key="id"
      :default-checked-keys="menuId"
      show-checkbox
      @check="handleCheck"
    >
    </el-tree>
    <button @click="logCheckedNodes">收集已选节点</button>
    <pre>{{ JSON.stringify(checkedNodes, null, 2) }}</pre>
  </div>
</template>
  1. <el-tree> 组件: 用于展示树形数据。

    • ref="tree": 用于引用该组件实例。
    • :data="menuOptions": 树的数据来源。
    • :props="treeProps": 控制树结构的属性配置。
    • node-key="id": 唯一节点标识字段。
    • :default-checked-keys="menuId": 默认选中的节点。
    • show-checkbox: 显示复选框。
    • @check="handleCheck": 选中节点时触发的事件。
  2. 按钮: 用于触发 logCheckedNodes 方法,收集并展示已选中的节点。

  3. 格式化的 JSON 预览: 用于展示 checkedNodes

脚本部分 (<script>)

<script>
export default {
  data() {
    return {
      menuId: [688, 689, 690, 691, 692],
      menuOptions: [
        { id: 543, label: "首页", business_type: 0 },
        {
          id: 575,
          label: "up评级后台",
          business_type: 0,
          children: [
            {
              id: 576,
              label: "up评级",
              business_type: 0,
              children: [
                { id: 688, label: "导入评级", business_type: 0 },
                { id: 689, label: "评级打分", business_type: 0 },
                { id: 690, label: "分页获取评级", business_type: 0 }
              ]
            },
            {
              id: 577,
              label: "运营复评",
              business_type: 0,
              children: [
                { id: 691, label: "重新评级", business_type: 0 },
                { id: 692, label: "分页获取评级", business_type: 0 }
              ]
            },
            {
              id: 578,
              label: "评级查询",
              business_type: 0,
              children: [
                { id: 693, label: "导出评级明细", business_type: 0 },
                { id: 694, label: "分页获取评级", business_type: 0 },
                { id: 695, label: "导入扶持up", business_type: 0 },
                { id: 696, label: "导入非扶持up", business_type: 0 },
                { id: 697, label: "主播重新评级", business_type: 0 }
              ]
            }
          ]
        }
      ],
      treeProps: {
        label: 'label',
        children: 'children',
        disabled: (data) => this.menuId.includes(data.id)
      },
      checkedNodes: []
    };
  },
  methods: {
    getCheckedNodes(nodes, checkedKeys) {
      return nodes.reduce((acc, node) => {
        if (checkedKeys.includes(node.id) && !this.menuId.includes(node.id)) {
          const newNode = { ...node };
          if (node.children) {
            newNode.children = this.getCheckedNodes(node.children, checkedKeys);
          }
          acc.push(newNode);
        } else if (node.children) {
          const childNodes = this.getCheckedNodes(node.children, checkedKeys);
          if (childNodes.length > 0) {
            const partialNode = { ...node, children: childNodes };
            acc.push(partialNode);
          }
        }
        return acc;
      }, []);
    },
    logCheckedNodes() {
      const checkedKeys = this.$refs.tree.getCheckedKeys(true);
      const checkedNodes = this.getCheckedNodes(this.menuOptions, checkedKeys);
      this.checkedNodes = checkedNodes;
      console.log('Checked Nodes:', checkedNodes);
    }
  }
};
</script>
  1. 数据:

    • menuId: 默认选中的节点 ID 数组。
    • menuOptions: 树形数据。
    • treeProps: 配置树结构显示的属性。
    • checkedNodes: 保存已选中的节点数据。
  2. 方法:

    • getCheckedNodes: 递归获取已选中的节点,排除掉 menuId 中的节点。
    • logCheckedNodes: 通过树的实例 this.$refs.tree 获取选中的节点 ID,并调用 getCheckedNodes 获取对应的节点数据,保存到 checkedNodes

详解getCheckedNodes 是一个递归函数,用于收集所有被选中的节点并返回一个不包含在 menuId 数组中的节点列表。以下是函数的详细解释:

getCheckedNodes(nodes, checkedKeys) {
  return nodes.reduce((acc, node) => {
    // 判断当前节点是否在选中列表中并且不在默认选中的节点列表中
    if (checkedKeys.includes(node.id) && !this.menuId.includes(node.id)) {
      const newNode = { ...node };
      // 如果当前节点有子节点,递归调用 getCheckedNodes 收集子节点
      if (node.children) {
        newNode.children = this.getCheckedNodes(node.children, checkedKeys);
      }
      // 将处理好的节点添加到结果集中
      acc.push(newNode);
    } else if (node.children) {
      // 如果当前节点不在选中列表中,但有子节点,将子节点传递下去处理
      const childNodes = this.getCheckedNodes(node.children, checkedKeys);
      if (childNodes.length > 0) {
        // 如果子节点中有任何节点被选中,将部分更新的节点添加到结果集中
        const partialNode = { ...node, children: childNodes };
        acc.push(partialNode);
      }
    }
    return acc;
  }, []);
}

详细解释

  1. 入参:

    • nodes: 当前处理的节点列表。
    • checkedKeys: 所有被选中的节点 ID 数组。
  2. 返回值:

    • 返回一个包含被选中的节点及其层级结构的数组。
  3. 步骤:

    • 1. 初始化累加器: 使用数组 reduce 方法,初始化一个空数组 acc 作为累加器。

    • 2. 遍历节点:

      • nodes 的每一个 node 进行处理:

      • 3.a. 是否选中并不在默认选中节点中:

        • 如果当前节点 node.idcheckedKeys 中,并且不在 menuId 中,说明该节点应该被选中。

        • 新建一个 newNode,复制当前节点的所有属性(浅拷贝)。

        • 3.a.i. 递归处理子节点:

          • 如果当前节点有子节点 children,递归调用 getCheckedNodes 处理子节点。
          • 将处理后的子节点数组赋值给 newNode.children
        • 3.a.ii. 添加到累加器:

          • 将 newNode 添加到累加器 acc 中。
      • 3.b. 子节点处理:

        • 如果当前节点没有被选中,但有子节点 children,继续处理子节点:

        • 3.b.i. 递归处理子节点:

          • 以当前节点的子节点作为参数调用 getCheckedNodes
          • 返回的子节点数组 childNodes
        • 3.b.ii. 添加部分节点:

          • 如果 childNodes 中有节点,说明某些子节点被选中,创建一个 partialNode
          • 将 partialNode(包含未选中的当前节点和被选中的子节点)添加到 acc 中。
    • 4. 返回累加器: 完成所有节点遍历,返回累加器 acc,它包含所有被选中的节点及其层级结构。

这个函数确保无论节点在树的哪个层级,只要被选中且不在默认选中的节点列表中,都将被捕获并保存在结果中。


原文地址:https://blog.csdn.net/weixin_41987016/article/details/142452668

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!