草庐IT

element-ui tree 异步树实现勾选自动展开、指定展开、指定勾选

追极 2023-03-28 原文

背景

项目中用到了vue的element-ui框架,用到了el-tree组件。由于数据量很大,使用了数据懒加载模式,即异步树。异步树采用复选框进行结点选择的时候,没法自动展开,官方文档找了半天也没有找到好的办法! 找不到相关的配置,或者方法可以使用。 经过调试与阅读elment-ui源码才发现有现成的方法可以进行结点展开。下面就介绍结点展开的实现!

1.监听复选框点击事件check

<el-tree
        :props="mulprops"
        :load="loadNode"
        lazy
        node-key="id"
        show-checkbox
        accordion
        @current-change="currentChange"
        :filter-node-method="filterNode"
        @check="handleCheck"
        ref="tree"
        :default-checked-keys="defaultCheckedNodes"
        :default-expanded-keys="defaultExpandedNodes"
    >
    </el-tree>

2.手动展开,使用node.expand()方法

handleCheck(nodeData,  treeChecked) {
      let node = this.$refs.tree.getNode(nodeData.id)
      //将选中的未展开的节点进行展开
      if(node.checked && !node.expanded){
        node.expand(function(){
          for(let i=0; i< node.childNodes.length; i++){
            node.childNodes[i].expand()
          }
        })
      }
    }

 

项目中的实现

一、复选框勾选后能自动展开并选中,先展开再勾选也可以自动展开

1.监听check-change事件

    <el-tree
        :props="mulprops"
        :load="loadNode"
        lazy
        node-key="id"
        show-checkbox
        accordion
        @check-change="handleCheckChange"
        :filter-node-method="filterNode"
        ref="tree"
        :default-checked-keys="defaultCheckedNodes"
        :default-expanded-keys="defaultExpandedNodes"
    >
    </el-tree>

2.编写展开勾选结点方法

handleCheckChange(nodeData, nodeSelected) {
      let tree = this.$refs.tree;
      let node = tree.getNode(nodeData.id)

      //展开选中的未展开的节点
      this.expandCheckedNotExpandNodes(node);

      //具体业务实现
      console.log(nodeData, nodeSelected)
    },
    //展开选中的未展开的节点
    expandCheckedNotExpandNodes(node) {
      let tree = this.$refs.tree;
      if (node.checked && !node.expanded && !node.isLeaf) {
        node.expand(function () {
          let childNodes = node.childNodes;
          for (let i = 0; i < childNodes.length; i++) {
            let childNode = childNodes[i];
            //手动触发check-change事件,事件处理函数中回继续调用此函数,形成递归展开
            tree.$emit('check-change', childNode.data, childNode.checked, childNode.indeterminate);
          }
        })
      }
    },

二、 展开指定结点

   <el-input type="text" v-model='nodeDataIds' placeholder="请输入结点数据ID(多个以逗号分割)"> ></el-input>
    <el-button type="primary" @click="expandNodes(nodeDataIds.split(','))">展开指定结点</el-button>
   

 

//展开匹配的结点,根结点默认展开
    expandNodes(nodeDataIds){
        let that = this;
        let tree = this.$refs.tree;
        let rootNode = tree.root;
        this.expandNode(rootNode, nodeDataIds);
    },
    //展开指定结点下匹配的结点
    expandNode(node, nodeDataIds){
        let that = this;
        //当前结点需要展开未展开,则展开(根结点默认展开)
        if(node.level==0 || nodeDataIds.indexOf(node.data.id) != -1){
           //展开孩子结点
           let expandChildren = function(){
               let childNodes = node.childNodes;
               for (let i = 0; i < childNodes.length; i++) {
                  let childNode = childNodes[i];
                  //递归展开孩子结点
                  that.expandNode(childNode, nodeDataIds);
               }
           }
           if(!node.expanded){
               //当前结点未展开则先展开,展开后再展开孩子结点
               node.expand(function(){
                    expandChildren();
               });
           }else{
                //当前结点已展开,直接展开孩子结点
                expandChildren();
           }
        }
    },

 

 

三. 勾选指定结点

1.异步树,需先展开指定结点,然后有数据了才能勾选上(即:展开父结点,子节点有了数据才能勾选上)

  <el-button type="primary" @click="checkNodes(nodeDataIds.split(','))">选中指定结点</el-button>
    

 2.设置默认勾选的结点,再调用展开方法会自动勾选上,适合写数据回显

default-checked-keys=['node001','node002']
expandNodes(nodeDataIds)

 

四、展开并勾选结点(支持异步树)牛逼版,实现展开回调

//展开匹配的结点,根结点默认展开
    expandNodes(nodeDataIds){
        let that = this;
        let tree = this.$refs.tree;
        let rootNode = tree.root;
        this.expandNode(rootNode, nodeDataIds, function(){
            that.checkNodes(['node001','node002']);
        });
    },
    //展开指定结点下匹配的结点
    expandNode(node, nodeDataIds, callback){
        let that = this;
        //递归进入
        that.recursiveEnter();

        //当前结点需要展开未展开,则展开(根结点默认展开)
        if(node.level==0 || nodeDataIds.indexOf(node.data.id) != -1){
           //展开孩子结点
           let expandChildren = function(){
               let childNodes = node.childNodes;
               if(childNodes.length > 0){
                   for (let i = 0; i < childNodes.length; i++) {
                      let childNode = childNodes[i];
                      //递归展开孩子结点
                      that.expandNode(childNode, nodeDataIds, callback);
                   }
               }
           }
           if(!node.expanded){
               //当前结点未展开则先展开,展开后再展开孩子结点
               node.expand(function(){
                    //展开孩子结点
                    expandChildren();

                    //递归退出
                    that.recursiveExit(callback);
               });
           }else{
                //当前结点已展开,直接展开孩子结点
                expandChildren();

                //递归退出
                that.recursiveExit(callback);
           }
        }else{
            //递归退出
            that.recursiveExit(callback);
        }
    },
    //递归计入计数剩余递归次数
    recursiveEnter(){
        this.recursiveRemainCount++;
        console.log('enter recursiveRemainCount', this.recursiveRemainCount)
    },
    //递归退出计数剩余递归次数
    recursiveExit(callback){
       this.recursiveRemainCount--;
       console.log('exit recursiveRemainCount', this.recursiveRemainCount)
       if(this.recursiveRemainCount==0){
         if(callback){
            callback();
         }
       }
    },
    checkNodes(nodeDataIds){
         let tree = this.$refs.tree;
         tree.setCheckedKeys(nodeDataIds, false)
    }

 

有关element-ui tree 异步树实现勾选自动展开、指定展开、指定勾选的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  4. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  5. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  7. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  8. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  9. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  10. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

随机推荐