hello world 开发工程师 2023-04-23 06:42 采纳率: 0%
浏览 99
已结题

vue2项目,实现四层checkbox嵌套联动

问题:vue2项目,实现四层checkbox嵌套联动;

img

<template>
  <div id="app">
    <div class="topCheckbox">
      <div
        v-for="(timeSheetItem, index) in timeSheetInfoData"
        :key="index"
        class="oneFloor"
      >
        
        <div class="oneTitle">
          <van-checkbox
            v-model="timeSheetItem.checked"
            :name="`${timeSheetItem.evaIds}${index}`"
            class="titleLift"
            icon-size="18px"
            @click="oneCheckboxClick(index, timeSheetItem)"
          >
            {{ timeSheetItem.userName }} {{ timeSheetItem.period }}
            {{ timeSheetItem.totalHour }}h
          </van-checkbox>
          <div class="titleRight" @click="oneFloorClick(timeSheetItem, index)">
            <span>{{ timeSheetItem.unflod % 2 === 0 ? "折叠" : "展开" }}</span>
            <div>
              <van-icon
                v-if="timeSheetItem.unflod % 2 === 0"
                name="arrow-up"
                size="16px"
              ></van-icon>
              <van-icon v-else name="arrow-down" size="16px"></van-icon>
            </div>
          </div>
        </div>

        
        <template v-if="timeSheetItem.unflod % 2 === 0">
          <div
            v-for="(itemSecond, indexSecond) in restList[index]"
            :key="indexSecond"
            class="twoFloor"
          >
            
            <div class="twoTitle">
              <van-checkbox
                v-model="itemSecond.checked"
                :name="`${itemSecond.evaIds}${index}`"
                class="titleLift"
                icon-size="15px"
                @click="
                  twoCheckboxClick(
                    index,
                    itemSecond,
                    timeSheetItem,
                    indexSecond
                  )
                "
              >
                {{ itemSecond.reportDate }} {{ itemSecond.week }}
                {{ itemSecond.hour }}h
              </van-checkbox>
              <div
                class="titleRight"
                @click="twoFloorClick(itemSecond, index, indexSecond)"
              >
                <span>{{ itemSecond.unflod % 2 === 0 ? "折叠" : "展开" }}</span>
                <div>
                  <van-icon
                    v-if="itemSecond.unflod % 2 === 0"
                    name="arrow-up"
                  ></van-icon>
                  <van-icon v-else name="arrow-down"></van-icon>
                </div>
              </div>
            </div>

            
            <template v-if="itemSecond.unflod % 2 === 0">
              <div
                v-for="(itemThird, indexThird) in itemSecond.list"
                :key="indexThird"
                class="threeFloor"
              >
                <van-checkbox
                  ref="checkboxThird"
                  v-model="itemThird.ckecked"
                  class="left"
                  :name="`${itemThird.evaIds}`"
                  icon-size="15px"
                  @click="checkboxClickThree(index, itemSecond)"
                ></van-checkbox>
                <div class="right">
                  
                  <div class="date">
                    {{ itemThird.taskName }}
                  </div>
                </div>
              </div>
            </template>
          </div>
        </template>
      </div>
    </div>
    <van-checkbox v-model="isCheckAll" @click="checkAll">全选</van-checkbox>
  </div>
</template>
<script>
// import Vue from 'vue'
import mockData from '../src/assets/util/js/mock'
export default {
  name: 'FourFloorCheckbox',
  data () {
    return {
      timeSheetInfoData: [],
      restList: [],
      isCheckAll: false
    }
  },
  created () {
    this.loadFirstList()
  },
  methods: {
    // 获取第一层数据
    loadFirstList () {
      setTimeout(() => {
        this.timeSheetInfoData = mockData.firstFloorData
      }, 200)
    },

    // 全选
    checkAll () {
      if (this.isCheckAll) {
        this.timeSheetInfoData.map((item) => {
          console.log(11)
          item.checked = true
          return item
        })
      } else {
        this.timeSheetInfoData.map((item) => {
          item.checked = false
          return item
        })
      }
    },
    // 点击第一层复选框
    oneCheckboxClick (index, item) {
      console.log('change1', item.checked, item.unflod)
      // this.$forceUpdate()

      // 与全选按钮的关系
      const allChecked = this.timeSheetInfoData.every(item => item.checked === true)
      const someChecked = this.timeSheetInfoData.some(item => item.checked === false)
      if (allChecked) {
        this.isCheckAll = true
      }
      if (someChecked) {
        this.isCheckAll = false
      }

      if (item.unflod !== 1) {
        this.$forceUpdate()
        if (item.checked) {
          this.restList[index].map((item) => {
            item.checked = true
            return item
          })
        } else {
          this.restList[index].map(item => {
            item.checked = false
            return item
          })
        }
      }
    },

    // 点击第一层展开/折叠  展开-发送接口拿剩余数据
    oneFloorClick (timeSheetItem, index) {
      // 第一次单击 展开 调接口
      if (timeSheetItem.unflod === 1) {
        this.loadRestList(timeSheetItem, index)
      } else {
        timeSheetItem.unflod++
      }
      this.$forceUpdate()
    },

    // 获取第二层及第三层的数据
    loadRestList (timeSheetItem, index) {
      setTimeout((item) => {
        console.log('调接口拿到数据')
        this.$set(this.restList, index, mockData.restData)

        if (timeSheetItem.checked) {
          this.restList[index].map(item => {
            item.checked = true
            return item
          })
        } else {
          this.restList[index].map(item => {
            item.checked = false
            return item
          })
        }

        timeSheetItem.unflod++ // 展开折叠板
      }, 200)
    },

    // 点击第二层复选框
    twoCheckboxClick (index, itemSecond, timeSheetItem, indexSecond) {
      console.log(2222, itemSecond.checked)
      // 与第一层的关系
      const allChecked = this.restList[index].every(item => item.checked === true)
      const someChecked = this.restList[index].some(item => item.checked === false)
      if (allChecked) {
        timeSheetItem.checked = true
      }
      if (someChecked) {
        timeSheetItem.checked = false
      }
    },

    // 点击第二层展开/折叠
    twoFloorClick (itemSecond, index, indexSecond) {
      itemSecond.unflod++
      this.$forceUpdate()
      if (itemSecond.checked) {
        console.log(2223)
        itemSecond.list.map((item) => {
          item.checked = true
          return item
        })
        // itemSecond.list.map((item) => { this.$set(item, 'checked', true) })
        // this.restList[index][indexSecond].list.forEach((val, indx) => {
        //   this.$set(this.restList[index][indexSecond].list[indx], 'checked', true)
        // })
      } else {
        console.log(2224)
        itemSecond.list.map((item) => {
          item.checked = false
          return item
        })
        // itemSecond.list.map((item) => { this.$set(item, 'checked', false) })
        // this.restList[index][indexSecond].list.forEach((val, indx) => {
        //   this.$set(this.restList[index][indexSecond].list[indx], 'checked', false)
        // })
      }
    },

    // 点击第三层复选框
    checkboxClickThree (index, itemSecond) {
      this.$forceUpdate()
      // 与第二层的关系
      const allChecked = itemSecond.list.every(item => item.checked === true)
      const someChecked = itemSecond.list.some(item => item.checked === false)
      if (allChecked) {
        itemSecond.checked = true
      }
      if (someChecked) {
        itemSecond.checked = false
      }
    },

    // 测试按钮点击
    testClick () {
      console.log('timeSheetData', this.timeSheetInfoData)
      console.log('restList', this.restList)
    }
  }
}
</script>

<style lang="less">
.oneTitle {
  display: flex;
  justify-content: space-between;
  padding: 20px 15px;
  border-bottom: 1px solid #2c3e50;
  .titleRight {
    display: flex;
    justify-content: flex-end;
  }
}
.twoFloor {
  padding: 15px 10px;
  .twoTitle {
    display: flex;
    justify-content: space-between;
    .titleLift {
      padding-left: 20px;
    }
  }
  .titleRight {
    display: flex;
    // justify-content: flex-end;
  }
}
.threeFloor {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  .left {
    padding-left: 30px;
  }
}
.topCheckbox {
  padding-bottom: 50px;
}
</style>


下面是模拟的后台数据:

const mockData = {}
mockData.firstFloorData = [
  {
    checked: false,
    evaIds: '450162,450163,450164,450165,450172,450173,450174,450175,450176,450177,450179,450180,450181,450274,450275',
    month: '0',
    period: '2023年01月',
    totalHour: '112',
    unflod: 1,
    userId: 1383,
    userName: '范令令',
    week: null,
    year: '2023'
  },
  {
    checked: false,
    evaIds: '450162,450163,450164,450165,450172,450173,450174',
    month: '0',
    period: '2023年08月',
    totalHour: '224',
    unflod: 1,
    userId: 1383,
    userName: '张三',
    week: null,
    year: '2023'
  },
  {
    checked: false,
    evaIds: '450162',
    month: '0',
    period: '2025年09月',
    totalHour: '189',
    unflod: 1,
    userId: 1383,
    userName: '李斯',
    week: null,
    year: '2023'
  }
]

mockData.restData = [
  {
    checked: false,
    evaIds: '450274',
    hour: '8.0',
    reportDate: '2023-01-30',
    unflod: 1,
    week: '周一',
    list: [
      {
        checked: false,
        comment: '',
        taskName: '学习歌单听得有点难过',
        taskSource: '部门日常任务',
        unflod: 1,
        week: '周一'
      },
      {
        checked: false,
        comment: '',
        taskName: '人要往前走,就要换歌单,以前的歌单太重了',
        taskSource: '部门日常任务',
        unflod: 1,
        week: '周一'
      }
    ]
  },
  {
    checked: false,
    evaIds: '450274',
    hour: '8.0',
    reportDate: '2023-01-30',
    unflod: 1,
    week: '周一',
    list: [
      {
        checked: false,
        comment: '',
        taskName: '学习歌单听得有点难过',
        taskSource: '部门日常任务',
        unflod: 1,
        week: '周一'
      },
      {
        checked: false,
        comment: '',
        taskName: '人要往前走,就要换歌单,以前的歌单太重了',
        taskSource: '部门日常任务',
        unflod: 1,
        week: '周一'
      }
    ]
  }
]

export default mockData


由于数据起初不是响应式,加上我思维混乱,搞晕了。

  • 写回答

5条回答 默认 最新

  • 乘风xs 2023-04-23 09:13
    关注

    两个思路:
    1.设置一个变量表示是否全选, isSelectedAll, 在全选按钮的响应中修改其值,在每个checkbox中取值为isSelectedAll与原本值的与值
    2.直接在全选按钮中的响应中遍历修改每个checkbox的值
    可远程帮助实现

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月26日
  • 创建了问题 4月23日