element中Tree 树形控件实现多选、展开折叠、全选全不选、父子联动、默认展开、默认选中、默认禁用、自定义节点内容、可拖拽节点、手风琴模式

news2024/11/20 6:36:45

目录

  • 1.代码实现
  • 2. 效果图
  • 3. 使用到的部分属性说明
  • 4. 更多属性配置查看element官网

1.代码实现

 <template>
  <div class="TreePage">
    <el-checkbox
      v-model="menuExpand"
      @change="handleCheckedTreeExpand($event, 'menu')"
      >展开/折叠</el-checkbox
    >
    <el-checkbox
      v-model="menuNodeAll"
      @change="handleCheckedTreeNodeAll($event, 'menu')"
      >全选/全不选</el-checkbox
    >
    <el-checkbox
      v-model="menuCheckStrictly"
      @change="handleCheckedTreeConnect($event, 'menu')"
      >父子联动</el-checkbox
    >

    <el-row :gutter="20" style="margin-top: 20px">
      <!--村数据-->
      <el-col :span="24">
        <div class="head-container">
          <el-input
            v-model="deptName"
            placeholder="请输入名称"
            clearable
            size="small"
            prefix-icon="el-icon-search"
            style="margin-bottom: 20px"
          />
        </div>
        <!-- 组织树 -->
        <div class="head-container">
          <el-tree
            ref="menu"
            :props="defaultProps"
            :default-expanded-keys="defaultExpandedKeys"
            :default-checked-keys="defaultCheckedKeys"
            :expand-on-click-node="false"
            :data="menuOptions"
            show-checkbox
            node-key="deptId"
            :check-strictly="!menuCheckStrictly"
            empty-text="加载中,请稍后"
            :filter-node-method="filterNode"
            @node-click="handleNodeClick"
            draggable
            @node-drag-start="handleDragStart"
            @node-drag-enter="handleDragEnter"
            @node-drag-leave="handleDragLeave"
            @node-drag-over="handleDragOver"
            @node-drag-end="handleDragEnd"
            @node-drop="handleDrop"
            :allow-drop="allowDrop"
            :allow-drag="allowDrag"
          >
            <!--自定义节点内容: 使用 scoped slot 会传入两个参数node和data,分别表示当前节点的 Node 对象和当前节点的数据。 -->
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <span>{{ node.label }}</span>
              <span>
                <el-button type="text" size="mini" @click="() => append(data)">
                  新增
                </el-button>
                <el-button
                  type="text"
                  size="mini"
                  @click="() => remove(node, data)"
                >
                  删除
                </el-button>
              </span>
            </span>
          </el-tree>
        </div>
      </el-col>
    </el-row>
    <el-button type="primary" @click="submitForm">确 定</el-button>
  </div>
</template>
        
<script>
let deptId = 10000;
export default {
  name: "TreePage2",
  props: {},
  data() {
    return {
      menuExpand: false,
      menuNodeAll: false,
      menuCheckStrictly: true,
      // 模拟数据
      menuOptions: [
        {
          deptId: 100,
          parentId: 0,
          parentName: null,
          ancestors: "0",
          deptName: "XX01街道",
          children: [
            {
              deptId: 1001,
              parentId: 100,
              parentName: null,
              ancestors: "0,100",
              deptName: "XX1-1村",
              children: [
                {
                  deptId: 10011,
                  parentId: 1001,
                  parentName: null,
                  ancestors: "0,100,1001",
                  deptName: "XX1-1-1村",
                  children: [],
                },
              ],
            },
            {
              deptId: 1002,
              parentId: 100,
              parentName: null,
              ancestors: "0,100",
              deptName: "XX1-2村",
              children: [
                {
                  deptId: 10021,
                  parentId: 1002,
                  parentName: null,
                  ancestors: "0,100,1002",
                  deptName: "XX1-2-1村",
                  children: [],
                  disabled: true, //禁用
                },
              ],
            },
            {
              deptId: 1003,
              parentId: 100,
              parentName: null,
              ancestors: "0,100",
              deptName: "XX1-3村",
              children: [],
            },
          ],
        },
        {
          deptId: 200,
          parentId: 0,
          parentName: null,
          ancestors: "0",
          deptName: "XX02街道",
          children: [
            {
              deptId: 2001,
              parentId: 200,
              parentName: null,
              ancestors: "0,200",
              deptName: "XX2-1村",
              children: [],
            },
            {
              deptId: 2002,
              parentId: 200,
              parentName: null,
              ancestors: "0,200",
              deptName: "XX2-2村",
              children: [],
            },
            {
              deptId: 2003,
              parentId: 200,
              parentName: null,
              ancestors: "0,200",
              deptName: "XX2-3村",
              children: [],
            },
          ],
        },
      ],
      // 村名称
      deptName: undefined,
      defaultProps: {
        children: "children",
        label: "deptName",
      },
      // 默认展开的节点的 key 的数组
      defaultExpandedKeys: [100, 10021],
      // 默认展开的节点的 选中 的数组
      defaultCheckedKeys: [1001],
    };
  },
  watch: {
    // 在需要对节点进行过滤时,调用 Tree 实例的filter方法,参数为关键字。
    // 需要注意的是,此时需要设置filter-node-method,值为过滤函数。
    // 根据名称筛选村社树
    deptName(val) {
      this.$refs.menu.filter(val);
    },
  },
  methods: {
    // 树权限(展开/折叠)
    handleCheckedTreeExpand(value) {
      let treeList = this.menuOptions;
      for (let i = 0; i < treeList.length; i++) {
        this.$refs.menu.store.nodesMap[treeList[i].deptId].expanded = value;
      }
    },
    // 树权限(全选/全不选)
    handleCheckedTreeNodeAll(value) {
      this.$refs.menu.setCheckedNodes(value ? this.menuOptions : []);
    },
    // 树权限(父子联动)
    handleCheckedTreeConnect(value) {
      this.menuCheckStrictly = value ? true : false;
    },
    // 过滤函数
    filterNode(value, data) {
      // console.log(value, data)
      if (!value) return true;
      return data.deptName.indexOf(value) !== -1;
    },
    // 左侧网格树-节点单击事件
    handleNodeClick(data) {
      console.log(data, "左侧网格树-节点单击事件");
    },
    // 所有菜单节点数据
    getMenuAllCheckedKeys() {
      // 目前被选中的菜单节点
      let checkedKeys = this.$refs.menu.getCheckedKeys();
      // 半选中的菜单节点
      let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys();
      checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
      return checkedKeys;
    },
    // 新增节点
    append(data) {
      const newChild = { deptId: deptId++, deptName: "test", children: [] };
      if (!data.children) {
        this.$set(data, "children", []);
      }
      data.children.push(newChild);
    },
    // 删除节点
    remove(node, data) {
      const parent = node.parent;
      const children = parent.data.children || parent.data;
      const index = children.findIndex((d) => d.deptId === data.deptId);
      children.splice(index, 1);
    },

    // 节点开始拖拽时触发的事件
    handleDragStart(node, ev) {
      console.log("drag start", node,ev);
    },
    //   拖拽进入其他节点时触发的事件
    handleDragEnter(draggingNode, dropNode, ev) {
      console.log("tree drag enter: ", dropNode.deptName,ev);
    },
    //   拖拽离开某个节点时触发的事件
    handleDragLeave(draggingNode, dropNode, ev) {
      console.log("tree drag leave: ", dropNode.deptName,ev);
    },
    //   在拖拽节点时触发的事件(类似浏览器的 mouseover 事件)
    handleDragOver(draggingNode, dropNode, ev) {
      console.log("tree drag over: ", dropNode.deptName,ev);
    },
    //   拖拽结束时(可能未成功)触发的事件
    handleDragEnd(draggingNode, dropNode, dropType, ev) {
      console.log("tree drag end: ", dropNode && dropNode.deptName, dropType,ev);
    },
    //   拖拽成功完成时触发的事件
    handleDrop(draggingNode, dropNode, dropType, ev) {
      console.log("tree drop: ", dropNode.deptName, dropType,ev);
    },
    //   拖拽时判定目标节点能否被放置。type 参数有三种情况:'prev'、'inner' 和 'next',
    // 分别表示放置在目标节点前、插入至目标节点和放置在目标节点后
    allowDrop(draggingNode, dropNode, type) {
      if (dropNode.data.deptName === "XX1-1-1村") {
        return type !== "inner";
      } else {
        return true;
      }
    },
    //   判断节点能否被拖拽
    allowDrag(draggingNode) {
      return draggingNode.data.deptName.indexOf("XX1-2-1村") === -1;
    },

    /** 提交按钮 */
    submitForm() {
      let menuIds = this.getMenuAllCheckedKeys();
      console.log(menuIds, "menuIds");
    },
  },
};
</script>
        
      
<style scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>
             

2. 效果图

在这里插入图片描述

3. 使用到的部分属性说明

  1. default-expanded-keys: 默认展开的节点的 key 的数组;
  2. expand-on-click-node: 是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点;
  3. node-key :每个树节点用来作为唯一标识的属性,整棵树应该是唯一的;
  4. filter-node-method: 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏;
  5. node-click :节点被点击时的回调;
  6. accordion: 是否每次只打开一个同级树节点展开;
  7. default-expand-all: 是否默认展开所有节点 ;
  8. 通过 draggable: 属性可让节点变为可拖拽;

4. 更多属性配置查看element官网

https://element.eleme.cn/#/zh-CN/component/tree

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1358472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

亚马逊店铺遇到账号申诉模版分享

1.表达诚意&#xff0c;先认错再说&#xff1a;我知道&#xff0c;最近我们在Amazon.com上作为卖家的表现已经低于亚马逊和我们自己的质量标准。 2.清楚分明的格式&#xff1a;我们库存管理的混乱导致了延迟发货&#xff0c;更糟糕的是&#xff0c;物品无法使用。当延迟发货和…

00 项目结构

文章目录 后端 后端 后端 - sky-common包 公共类&#xff0c;工具类&#xff0c;常量类- constant 常量类- context 上下文有关的- enumenation 枚举- exception 自定义异常类- json json处理类- properties boot相关的配置属性类- result 结果类- uti…

【React系列】React中的CSS

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. React中的css方案 1.1. react 中的 css 事实上&#xff0c;css 一直是 React 的痛点&#xff0c;也是被很多开发…

gitlab高级功能之Kubernetes Agent介绍

文章目录 1. 前置条件2. 简介3. GitLab Kubernetes Agent 的部署3.1 启用 Agent 服务端3.2 创建 Agent 配置和清单仓库 4. 安装agent4.1 连接k8s集群4.2 在集群中部署4.3 修改资源清淡&#xff0c;调整pod的副本数 5. 思考 1. 前置条件 gitlab 14.5 专业版k8s集群helm客户端工…

风车模型与代码

这个模型使用NetLogo乌龟来重复绘制圆圈&#xff0c;定期转动&#xff0c;以便显示出类似万花筒或风车的效果。这是一个演示&#xff0c;展示了一组简单的代理规则如何产生复杂而美丽的图案。 内部工作原理非常简单。创建了许多乌龟&#xff0c;它们的笔都是放下的&#xff08…

一文全面了解 LSM BPF (含实战,强烈建议收藏)

本文地址&#xff1a;https://www.ebpf.top/post/lsm_bpf_intro 文章目录 1. 安全背景知识2. 内核安全策略模块通用框架 LSM2.1 LSM 框架介绍2.2 LSM 架构2.3 LSM 中的钩子函数 3. LSM BPF3.1 BCC 实践3.2 libbpf-bootstrap 框架实践 4. 总结5. 附录&#xff1a;LSM 热修内核漏…

Java 支持表情包存储 Incorrect string value: ‘\\xF0\\x9F\\x98\\x8A\\xF0\\x9F...‘

一&#xff0c;前言 最近测试提出了一个比较刁钻的bug 在提交表单数据的时候&#xff0c;支持表情输入&#xff0c;如下 看了一下前端参数&#xff0c;也是正常传递 但是调用接口的时候&#xff0c;后端却报错 Cause: java.sql.SQLException: Incorrect string value: \\xF0…

【python】使用fitz包读取PDF文件报错“ModuleNotFoundError: No module named ‘frontend‘”

【python】使用fitz包读取PDF文件报错“ModuleNotFoundError: No module named ‘frontend’” 正确解决过程 在读取PDF文件时&#xff0c;我使用了fitz包&#xff0c;当使用代码import fitz导入该包时&#xff0c;出现了报错&#xff1a; 于是我直接使用以下代码安装fronten…

技术查漏补缺(1)Logback

一、下定义&#xff1a;Logback是一个开源的日志组件 二、Logback的maven <!--这个依赖直接包含了 logback-core 以及 slf4j-api的依赖--> <dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><v…

基于Kettle开发的web版数据集成开源工具(data-integration)-介绍篇

目录 &#x1f4da;第一章 官网介绍&#x1f4d7;目标实现&#xff1a;让kettle使用更简单&#x1f4d7;架构及组成 &#x1f4da;第二章 核心功能&#x1f4da;第三章 对比Kettle&#x1f4d7;工具栏位比对&#x1f4d7;工具栏组件内容比对&#x1f4d7;扩展&#xff1a;WebSp…

【CMake】5. 单项目多模块添加第三方依赖示例工程

CMake 示例工程代码 https://github.com/LABELNET/cmake-simple 单项目单模块示例工程 https://github.com/LABELNET/cmake-simple/tree/main/simple-mod-deps 这里引入 C gRPC 依赖&#xff0c;进行示例 1. 多模块工程 第三方依赖 CMake 多模块工程&#xff0c;这是一个…

Android 项目工程配置签名文件

1. Android签名证书(.keystore) Android平台打包发布apk应用&#xff0c;需要使用数字证书&#xff08;.keystore文件&#xff09;进行签名&#xff0c;用于表明开发者身份。   Android证书的生成是自助和免费的&#xff0c;不需要审批或付费。   可以使用JRE环境中的keyto…

mariadb实现主从同步

准备两台服务器 Mariadb-Master&#xff1a;192.168.44.150 Mariadb-Backup&#xff1a;192.168.44.148 安装mariadb&#xff1a; https://blog.csdn.net/qq_50247813/article/details/135402502?spm1001.2014.3001.5502 组从复制原理如下 修改主数据库配置如下 vi /etc/my.…

Kotlin/JS工程构建及编译运行到浏览器

概述 Kotlin/JS 提供了转换 Kotlin 代码、Kotlin 标准库的能力&#xff0c;并且兼容 JavaScript 的任何依赖项。Kotlin/JS 的当前实现以 ES5 为目标。 使用 Kotlin/JS 的推荐方法是通过 kotlin.multiplatform Gradle 插件。它提供了一种集中且便捷的方式来设置与控制以 JavaS…

大数据框架ElasticSearch学习网站,让你的技能瞬间升级!

介绍&#xff1a;Elasticsearch是一个分布式、免费和开放的搜索和分析引擎&#xff0c;它适用于所有类型的数据&#xff0c;包括文本Elasticsearch是一个分布式、免费和开放的搜索和分析引擎&#xff0c;它适用于所有类型的数据&#xff0c;包括文本、数字、地理空间、结构化和…

如何保障开放网络边界安全?

针对开放式网络&#xff08;办事大厅、视频网络等&#xff09;&#xff0c;如何在内部网络构建起一道安全屏障&#xff0c;有效解决广大用户普遍存在的无法保证网络边界完整、边界安全、公共场所终端摄像头管理、办事大厅智能设备&#xff08;一体机等&#xff09;管理、开放场…

1- forecasting at scale论文阅读

目录 1. 什么是时间序列2. 什么是时间序列预测3. 时间序列预测的范式4. 时间序列的专有名词介绍5. 时间序列评估 1. 什么是时间序列 按时间先后顺序出现的有序序列 2. 什么是时间序列预测 点预测&#xff1a;预测未来的某一个时间点&#xff0c;它的值到底是多少&#xff0c…

手机卡丢了不要急,全新补卡攻略赶紧收藏!

最近收到一些小伙伴的留言&#xff0c;手机卡办了好几张&#xff0c;所以就出现了手机卡丢失的现象。手机卡丢失补办更是让一些小伙伴们摸不着头脑。怎么补&#xff1f;如何补&#xff1f;需要哪些资料等等一系列的问题&#xff0c;让许多小伙伴都无从下手。今天小编就给大家整…

当试图回复传入消息时,消息应用程序会闪烁

问题描述&#xff1a; Actual Results: Unable to reply for incoming message as Messaging app flickers and closes. Expected Results: User should be able to send reply for incoming messages. Reproduction Steps: Stay in home screen. Receive an incoming mes…

Vue-2、初识Vue

1、helloword小案列 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>初始Vue</title><!--引入vue--><script type"text/javascript" src"https://cdn.jsdelivr.n…