vue(移动端)实现部门/职级树形结构展示

一、需求分析:
1.部门按照树形结构展示一级、二级目录;
2.当一级目录选中时,二级目录自动全选;
在这里插入图片描述
3.当二级目录全选时,一级目录自动选中,反之,有一个二级没选中,一级就不被选中;
在这里插入图片描述
4.添加全选功能。
在这里插入图片描述在这里插入图片描述
二、上代码
备注:此处引用了vant组件的复选框功能。

<template>
  <div id="tree">
    <div @click="checkAllFun">
       <van-checkbox-group v-model="radio" class="checkAll" >
         <van-checkbox name="1" checked-color="#ee0a24"><div style="color:#E03716">全选</div></van-checkbox>
      </van-checkbox-group>
    </div>
      <div class="checkThem">
         <div v-for="item in firstAllList" :key="item.id">
           <!-- 一级的 -->
            <div class="check_checkThem_first flex-h flex-vh-center">
                <img src="open.png" class="img" v-show="firstFlag==item.id" @click.stop="firstChack('up',item)">
                <img src="down.png" class="img" v-show="firstFlag!=item.id" @click.stop="firstChack('down',item)">
                <van-checkbox-group v-model="firstList">
                  <van-checkbox :name="item.id" checked-color="#ee0a24" @click="firstClick(item.id)">{{item.name}}</van-checkbox>
               </van-checkbox-group>
            </div>
            <!-- 二级的 -->
            <div class="check_checkThem_second flex-h flex-vh-center" v-show="secondFlag==item.id"
             v-for="them in item.children" :key="them.id">
               <van-checkbox-group v-model="secondList">
                 <van-checkbox :name="them.id" checked-color="#ee0a24" @click="secondClick">{{them.name}}</van-checkbox>
               </van-checkbox-group>
            </div>
         </div>
      </div>
  </div>
</template>
<script>
import Vue from 'vue';
import { Checkbox, CheckboxGroup } from 'vant';
import {get} from "@/request/axios.js";
Vue.use(Checkbox);
Vue.use(CheckboxGroup);
export default {
  data() {
    return {
       radio: [],//全选的
       firstList:[],//一级选中的
       firstListCopY:[],//记录一级选中的条数
       secondList:[],//二级选中的
       firstFlag:'',//一级
       secondFlag:'',//二级
       firstAllList:[{
         name:'哈哈',
         id:'1',
         children:[{
           name:'孩子',
           id:'2'
         }],
         flagList:[],//存放被选中的children里的id
       }],//一级查询总数据
    };
  },
  mounted() {
      this.getFirstList();
  },
  methods: {
      //全选
      checkAllFun(){
        //全选操作前要清空原有已选列表,否则会出现重复数据,影响后边一级全选后联动全选按钮的判断
         this.firstList=[];
         this.secondList=[];
         //此时还未全选-点击之后进行全选操作
         if(this.radio.length===0){
            this.firstAllList.forEach(item=>{
                this.firstList.push(item.id);
                //此处用于记录当一级按钮被触发时,是新添加的还是取消的
                this.firstListCopY = JSON.parse(JSON.stringify(this.firstList));
                item.children.forEach(them=>{
                  if(them){
                    this.secondList.push(them.id);
                  }  
                })
            })       
         }else{
           //此时已全选-点击之后进行取消全选操作
            this.firstList=[];
            this.secondList=[];
            this.firstListCopY=[];
         }
      },
      //第一层点击
      firstChack(falg,item){
        if(falg==='down'){
          //要展开啦
          //展开过程中查看是否已经存在,如果不存在,需要查询二级部门的接口
          if(item.children.length===0){
             this.getSecondList(item,item.id);
          }else{
             this.secondFlag = item.id;
             this.firstFlag = item.id;
          }
        }else{
          //要关闭啦
           this.secondFlag = '';
           this.firstFlag = ''
        } 
      },
      //获取第一级数据
      getFirstList(){
        get(`url`).then(data=>{
              this.firstAllList = data;
              this.firstAllList.forEach(item=>{
                //存放二级数据
                item.children = [];
                //存放children里的被选id,
                //用于二级都被选中后联动一级被“选中”;反之,取消一级被选中
                item.flagList = [];
              }) 
        })
      },
      //获取第二级数据
      getSecondList(item,id){
          get(`url/${id}`).then(data=>{
              item.children = data;
              if(data.length!==0){
                this.secondFlag = item.id;
                this.firstFlag = item.id;
              }
              //全选
              if(this.radio.length===1){
                //如果是全选情况下,展开二级部门,需要进行选中添加
                item.children.forEach(them=>{
                  if(them){
                    this.secondList.push(them.id);
                  }  
                })
              }else{
                //非全选条件下
                 //一级已经选择
                  this.firstList.forEach(them=>{
                    if(them===item.id){
                        item.children.forEach(them=>{
                          if(them){
                            this.secondList.push(them.id);
                          }  
                        })
                    }
                  }) 
              } 
         })
      },
      //一级被点击
       firstClick(val){
          //添加全选/及反选操作
          if(this.firstList.length===this.firstAllList.length){
             this.radio = ['1'];
          }else{
             this.radio = [];
          }
          if(this.firstListCopY.length>this.firstList.length){
            //证明删除了一个一级的
             this.firstAllList.forEach(item=>{
              if(val===item.id){
                  item.children.forEach(code=>{
                    //找到对应一级val的所有二级进行删除
                   this.secondList.splice(this.secondList.findIndex(item => item=== code.id), 1)
                  })
              }
            })
          }else{
            //证明添加了一个一级的
             this.firstAllList.forEach(item=>{
                if(val===item.id){
                  if(item.children){
                      item.children.forEach(code=>{
                      let b =  this.secondList.indexOf(code.id);
                      //如果之前该一级部门下的二级没有存在已选列表中,就添加进去
                      if(b==-1){
                           this.secondList.push(code.id);
                      }
                    })
                  }  
                }
            })
          }
          //同步更新,为下次一级被触发时判断使用
          this.firstListCopY = JSON.parse(JSON.stringify(this.firstList));
      },
      //二级被触发
      secondClick(){
            //每次需要先清空flagList,避免影响下边的逻辑判断
            this.firstAllList.forEach(item=>{
                item.flagList = [];
            })
            this.secondList.forEach(item=>{
              this.firstAllList.forEach((them)=>{  
                  if(them.children){
                    them.children.forEach(code=>{
                      if(item===code.id){
                            them.flagList.push(code.id);
                      }
                       //判断二级是否都被选中,如果全部选中,就将对应的一级添加进已选列表
                      if(them.flagList.length==them.children.length){
                       //没有在一级已选列表中找到该点击的二级对应的一级Id-添加进去
                        let a =  this.firstList.indexOf(them.id);
                        if(a==-1){
                           this.firstList.push(them.id);
                        }
                      }else{
                        //反之,如果二级没有被全选中,需要去掉对应一级的被选
                        if(this.firstList.length===0){
                          return false;
                        }
                        this.firstList.forEach((id,i)=>{
                          if(id===them.id){
                               this.firstList.splice(i,1);
                          }  
                        })
                      } 
                    }) 
                  }
              })
            })
            //判断此时是否已经全部选中
            if(this.firstList.length===this.firstAllList.length){
             this.radio = ['1'];
            }else{
             this.radio = [];
            }
      }
  },

};
</script>
<style lang="scss" scoped>
.checkAll /deep/ .van-checkbox,
.check_checkThem_first,
.check_checkThem_second{
    height: 54px; 
    border-bottom: 1px solid #ebedf0;//联调完删除
}
.check_checkThem_second{
  width:88%;
  margin-left:12%;
}
.img{
  width:12px;
  height:12px;
  margin-right:2%;
}
</style>


  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值