vueH5级联组件,实现全选,非全选

  • Post author:
  • Post category:vue


实现效果:

在这里插入图片描述

vue代码:

<template>
  <div>
    <van-popup
      v-model="isVanshow"
      position="bottom"
      :round="true"
      @click-overlay="cancel"
    >
      <div class="personal-box">
        <div class="title">{{ title }}</div>
        <div
          class="person-list"
        >
          <div class="item-box">
            <div v-for="(item,index) in options" :key="index" class="item-wrap" :class="{'backColor':item.backColor}" @click="firstClick(index,item)">
              <van-checkbox v-model="item.checked" shape="square" @change="firstChange(index,item)" :class="{'line':item.iconClass === 'line','empty':item.iconClass === 'empty'}">{{item.label}}</van-checkbox>
              <van-icon name="arrow" v-if="index"/>
            </div>
          </div>
          <div class="item-box" v-if="options[firstIndex]">
            <div v-for="(s,index) in options[firstIndex].children" :key="index" class="item-wrap">
              <van-checkbox v-model="s.checked" shape="square" @change="secChange(index,s)" :class="{'line':s.iconClass === 'line' && !index,'empty':s.iconClass === 'empty'}">{{s.label}}</van-checkbox>
            </div>
          </div>
        </div>
        <van-tabbar
          ref="tabbarHeight"
          class="floot-but"
        >
          <div class="checked-but">
            <div
              class="but"
              @click="cancel"
            >取消</div>
            <div
              class="but sumbit-but"
              @click="confirm"
            >确认</div>
          </div>
        </van-tabbar>
      </div>
    </van-popup>
  </div>
</template>

js代码:

<script>
export default {
  name: 'selectPopup',
  components: {},
  data () {
    return {
      title: '',
      isVanshow: false,
      selectOneIdList: [],
      selectTwoIdList: [],
      selectNameList:[],
      selectList: [],
      firstIndex:1,
      options:[]
    }
  },
  mounted () {
  },

  methods: {
    firstClick(i){
      if(!i) return
      this.firstIndex = i
      this.options.map((item,index)=>{
        item.backColor = i === index
      })
    },
    firstChange(i,data){
      // 第一级全选/非全选   所有一级或二级全选/非全选
      if(i === 0){
        this.options.map((opt)=>{
          opt.checked = data.checked
          opt.iconClass = ''
          opt.children?.map((row)=>{
            row.checked = opt.checked
            row.iconClass = ''
          })
        })
      }else{
        // 第一级选中/取消,所有子级选中/取消
        data.children.map((item)=>{
          item.checked = data.checked
        })
        // 第一级所有的选中/取消,第一级的'全部'选中/取消
        let falseNUm = 0
        let trueNum = 0
        this.options.forEach((row,i)=>{
          if(!row.checked && row.iconClass !== 'line' && i){
            falseNUm ++
          }
          if(row.checked && row.iconClass !== 'line' && i){
            trueNum++
          }
        })
        if(trueNum === this.options.length-1 || falseNUm === this.options.length-1){
          this.options[0].checked = data.checked
          this.options[0].iconClass = ''
        }else{
          this.options[0].iconClass = 'line'
        }
      }
    },
    secChange(i,data){
      if(i === 0){
        // 处理二级的'全部'取消和勾选,对应的兄弟级和父级状态
        this.options[this.firstIndex].checked = data.checked
      }
      else if(!data.checked){
        let falseNum = 0
        this.options[this.firstIndex].children.map((opt,f)=>{
          if(!opt.checked && f){
            falseNum ++
          }
        })
        const childLength = this.options[this.firstIndex].children.length-1
        if(falseNum === childLength){
          // 第二级除了'全部',全部取消,则父级取消,所有兄弟级取消
          this.options[this.firstIndex].checked = data.checked
          this.options[this.firstIndex].iconClass = ''
          this.options[this.firstIndex].children[0].iconClass = ''

          // 判断如果此时第一级除了'全部'全取消,则'全部'取消
          let falseNUm = 0
          this.options.forEach((row,i)=>{
            if(!row.checked && row.iconClass !== 'line' && i){
              falseNUm++
            }
          })
          if(falseNUm === this.options.length-1){
            this.options[0].checked = data.checked
            this.options[0].iconClass = ''
          }else{
            this.options[0].iconClass = 'line'
          }
        }else{
          // 第二级,取消除了'全部'的任何元素,则'全部'显示'-',父级显示'-',第一级的'全部'显示'-'
          this.options[this.firstIndex].iconClass = 'line'
          this.options[this.firstIndex].children[0].iconClass = 'line'
          this.options[0].iconClass = 'line'
        }
      }
      else if(data.checked){
        let trueNum = 0
        this.options[this.firstIndex].children.map((opt,f)=>{
          if(opt.checked && f){
            trueNum ++
          }
        })
        const childLength = this.options[this.firstIndex].children.length-1
        if(trueNum === childLength){
          // 第二级除了'全部',全部选中,则父级选中,所有兄弟级选中
          this.options[this.firstIndex].checked = data.checked
          this.options[this.firstIndex].iconClass = ''
          this.options[this.firstIndex].children[0].iconClass = ''
          
          // 判断如果此时第一级除了'全部'全选中,则'全部'选中
          let trueNum = 0
          this.options.forEach((row,i)=>{
            if(row.checked && row.iconClass !== 'line' && i){
              trueNum++
            }
          })
          if(trueNum === this.options.length-1){
            this.options[0].checked = data.checked
            this.options[0].iconClass = ''
          }else{
            this.options[0].iconClass = 'line'
          }
        }else {
          // 第二级,选中除了'全部'的任何元素,则'全部'显示'-',父级显示'-',第一级的'全部'显示'-'
          this.options[this.firstIndex].iconClass = 'line'
          this.options[this.firstIndex].children[0].iconClass = 'line'
          this.options[0].iconClass = 'line'
        }
      }
    },
    // 取消 关闭弹出框
    cancel () {
      this.isVanshow = false
      this.$emit('cancel')
    },
    // 确认
    confirm () {
      this.selectOneIdList = []
      this.selectTwoIdList = []
      this.selectNameList = []
      this.options.forEach((item,index)=>{
        if(item.checked && item.iconClass === '' && index){
          this.selectOneIdList.push(item.value)
          this.selectNameList.push(item.label)
        }else{
          item.children?.forEach((row,i)=>{
            if(row.checked && i){
              this.selectTwoIdList.push(row.value)
              this.selectNameList.push(row.label)
            }
          })
        }
      })
      this.isVanshow = false
      console.log("selectNameList",this.selectNameList)
      this.$emit('confirm', this.selectOneIdList,this.selectTwoIdList,this.selectNameList)
    },
    // 打开弹出窗
    isShow (str,list,name,isFirst) {
      this.title = str
      this.options= list
      this.isVanshow = !isFirst
    }
  }
}

</script>

css代码:

<style lang='less' scoped>
.personal-box {
  display: flex;
  flex-direction: column;
  .title {
    width: 100%;
    height: 56px;
    border-bottom: 1px solid #e5e5e5;
    font-size: 18px;
    color: #323233;
    font-weight: 600;
    padding-left: 16px;
    display: flex;
    align-items: center;
  }
  .person-list {
    height: 264px;
    border-top: 1px solid #ebedf0;
    border-bottom: 1px solid #ebedf0;
    padding: 5px 16px 0;
    box-sizing: border-box;
    display: flex;
    justify-content: space-around;
    .item-box{
      font-size: 12px;
      width: 50%;
      overflow-y: scroll;
      overflow-x: hidden;
      .item-wrap{
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 32px;
        padding: 0 12px;
      }
      .backColor{
        background: #F3F4F7;
      }
    }
    /deep/ .van-checkbox__icon{
      width: 16px;
      height: 16px;
      line-height: 16px;
      font-size:16px
    }
    /deep/ .van-checkbox__icon .van-icon{
      width: 16px;
      height: 16px;
    }
    /deep/ .van-checkbox__label{
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    /deep/ .line .van-icon-success:before{
      content: "-";
    }
    /deep/ .line .van-checkbox__icon .van-icon{
      color: #fff;
      background-color: #1989fa;
      border-color: #1989fa;
    }
    /deep/ .empty .van-icon-success:before{
      content: "";
    }
    /deep/ .empty .van-checkbox__icon--checked .van-icon{
      background-color:#ffffff;
      border-color: #c8c9cc;
    }
  }
  .floot-but {
    display: block;
    height: 68px;
    box-shadow: 0px -1px 10px rgba(0, 0, 0, 0.03);
    position: relative;
    .checked-but {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 0 16px;
      box-sizing: border-box;
      margin-top: 12px;
      .but {
        height: 44px;
        width: 165.5px;
        display: flex;
        justify-content: center;
        align-items: center;
        border: 1px solid #128A78;
        border-radius: 23px;
        color: #128A78;
      }
      .sumbit-but {
        background: #128A78;
        color: #ffffff;
      }
    }
  }
}
</style>



版权声明:本文为weixin_42398301原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。