1

实际项目中,除了基本的树结构,有时还需扩展。如下图层级关系的递归调用,红框中的部分为完全递归组件。

image.png

父级:
template

<div class="dept-tree-show">
      <div class="teer-deep">
        <div class="per-teer first-teer clearfix">
          <template v-for="(item) in deptlist">
            <div class="pt-item ft-item"
              :key="item.id"
              v-if="item.treeType==activedepttree.code"
              :class="{
                'disactive': teer2,
                'active': (teer2&&teer2.code==item.code)
              }"
              @click.stop="openChildren(item)">
              <div class="top-title">{{item.name.slice(0,2)}}</div>
              <div class="total-more" title="人员列表" 
                @click.stop="showRelatedUsers(item)">
                <i :class="item.userloading?'el-icon-loading':'fa fa-users'"></i>
              </div>
              <div class="total-title">{{item.name}}</div>
              <!-- <div class="total-code">{{item.code}}</div> -->
              <div class="total-children" @click.stop="openChildren(item)">
                {{(item.children&&item.children.length)?item.children.length:0}} 
                <i :class="(teer2&&teer2.code==item.code)?'el-icon-arrow-up':'el-icon-arrow-down'"></i>
              </div>
            </div>
          </template>
        </div>
        <secondtree 
        v-if="teer2" 
        :openitem="teer2" 
        @closetopChildren="closetopChildren" 
        @showRelatedUsers="showRelatedUsers"></secondtree>
      </div>
    </div>

js:

//....不完整代码
import secondtree from './dept/childrenteer.vue'
//....不完整代码
components:{
    secondtree
  }
//....不完整代码

子级:

<template>
<div class="wrap-wrap">
  <div class="children-teer-wrap" @click.stop v-if="opendata">
    <div class="breaker" :id="opendata.id">
      <div class="line">
        <div class="line-left"></div>
        <div class="line-right"></div>
      </div>
      <div class="baseinfo">
        <div class="l-title">{{opendata.name}}</div>
        <div class="l-close" @click.stop="closeChildren(opendata)">收起</div>
      </div>
    </div>
    <div class="per-teer children-teer clearfix">
      <template v-for="(item) in opendata.children">
        <div 
          class="pt-item ct-item "
          :key="item.id"
          @click.stop="openChildren(item)"
          :class="{
            'disactive': treedata,
            'active': (treedata&&treedata.code==item.code)
          }">
          <div class="top-title">{{item.name.slice(0,2)}}</div>
          <div class="total-title">{{item.name}}</div>
          <div class="total-more" title="人员列表" @click.stop="showRelatedUsers(item)"><i :class="item.userloading?'el-icon-loading':'fa fa-users'"></i></div>
          <!-- <div class="total-code">{{item.code}}</div> -->
          <div class="total-children"
            @click.stop="openChildren(item)">
            {{(item.children&&item.children.length)?item.children.length:0}} 
            <i :class="(treedata&&treedata.code==item.code)?'el-icon-arrow-up':'el-icon-arrow-down'"></i>
          </div>
        </div>
      </template>
    </div>
  </div>
  <childrentree v-if="treedata" :openitem="treedata" @unActiveParent="unActiveParent" @closeChildren="closeChildren" @showRelatedUsers="showRelatedUsers"></childrentree>
</div>
  
</template>
<script>
export default {
  name:"childrentree",
  props:{
    openitem:{
      type: Object,
      default: () => {},
    }
  },
  watch:{
    openitem(val){
      this.opendata=val;
      this.treedata=""
    }
  },
  data(){
    return{
      opendata:this.openitem,
      treedata:""
    }
  },
  methods: {
    openChildren(data){
      if(this.treedata && this.treedata.code && data&& data.code && this.treedata.code==data.code){
        this.treedata="";
      }else{
        if(data&&data.children && data.children.length){
          this.treedata=data;
          this.$nextTick(()=>{
            document.getElementById(data.id).scrollIntoView({behavior: "smooth"})
          })
          //
        }
      }
    },
    unActiveParent(){
      this.treedata="";
    },
    closeChildren(data){
      this.opendata="";
      this.$emit('unActiveParent');
      this.$emit('closetopChildren');
    },
    showRelatedUsers(data){
      this.$emit("showRelatedUsers",data)
    }
  },
}
</script>

一些重要的废话放到最后:
1:子组件,即需要递归使用的组件,在js中是要声明name(name:"childrentree")。这样子组件在本身就可以直接使用本身。
2:本例从第二层节点才开始使用递归,所以写发有冗余,可按需精简
3:子组件的事件需要按需区分是要发起仅紧挨着的上层事件(this.$emit('unActiveParent');)还是顶层事件(this.$emit('closetopChildren');)。可以通过接受的方法名进行区分
4:展开某一节点后,节点子集的顶部,即大括号顶部的话,可以使用:(根据具体场景自行判断是否需要使用$nextTick)

document.getElementById(data.id).scrollIntoView({behavior: "smooth"})

如有问题请指正,如有更简洁的事项方式请留下链接(✿◡‿◡)


charlotteeeeeee
74 声望7 粉丝