動手擼了下基於Vue的類樹形全選與反選組件

文章先發佈於個人我的博客站點上,戳這裏css

最近,因爲公司後臺管理系統重構,須要一個用到如圖所示的一個功能:html

項目使用的Vue和elementUInode

一共有4級菜單,要實現全選和反選功能,當下級有一個被選中時,上級也要被選中;當下級所有未被選中時,上級也不能被選中。web

網上搜了一圈也沒有找到合適的,elementUI的tree組件雖然功能能實現,可是改樣式又不方便,因而,只好本身擼一個了。。。。不寫不知道本身有多菜!這個東西竟然耗時一天。。後端

這個功能被抽離出來,作成了一個單獨的組件。bash

下面記錄下主要的代碼: 後臺返回的菜單數據格式flex

let menuData = [
    {
        "id": 1,
        "menName": "管理模式",
        "path": "manageMode",
        "businessCode": "manageMode",
        "parentId": 0,
        "isChecked": null,
        "menLevel": 1,
        "subMenuPermissionsVO": [
            {
                "id": 105,
                "menName": "首頁",
                "path": "/index",
                "businessCode": "index",
                "parentId": 1,
                "isChecked": null,
                "menLevel": 2,
                "subMenuPermissionsVO": []
            },
            {
                "id": 106,
                "menName": "工做報表",
                "path": "/report",
                "businessCode": "report",
                "parentId": 1,
                "isChecked": null,
                "menLevel": 2,
                "subMenuPermissionsVO": [
                    {
                        "id": 107,
                        "menName": "數據總攬",
                        "path": "/reportOverView",
                        "businessCode": "reportOverView",
                        "parentId": 106,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    },
                    {
                        "id": 109,
                        "menName": "客服",
                        "path": "/reportService",
                        "businessCode": "客服",
                        "parentId": 106,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": [
                            {
                                "id": 110,
                                "menName": "工做報表",
                                "path": "/report-service-workreport",
                                "businessCode": "工做報表",
                                "parentId": 109,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            },
                            {
                                "id": 111,
                                "menName": "工做質量報表",
                                "path": "/report-service-qualityreport",
                                "businessCode": "工做質量報表",
                                "parentId": 109,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            }
                        ]
                    },
                    {
                        "id": 112,
                        "menName": "留言報表",
                        "path": "/reportLeaveWords",
                        "businessCode": "留言報表",
                        "parentId": 106,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    },
                    {
                        "id": 113,
                        "menName": "訪問軌跡",
                        "path": "/reportWebsite",
                        "businessCode": "訪問軌跡",
                        "parentId": 106,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    }
                ]
            },
            {
                "id": 114,
                "menName": "歷史會話",
                "path": "/history",
                "businessCode": "歷史會話",
                "parentId": 1,
                "isChecked": null,
                "menLevel": 2,
                "subMenuPermissionsVO": []
            },
            {
                "id": 115,
                "menName": "客服管理",
                "path": "/service",
                "businessCode": "客服管理",
                "parentId": 1,
                "isChecked": null,
                "menLevel": 2,
                "subMenuPermissionsVO": [
                    {
                        "id": 116,
                        "menName": "全部客服",
                        "path": "/service-all",
                        "businessCode": "全部客服",
                        "parentId": 115,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    },
                    {
                        "id": 117,
                        "menName": "角色設置",
                        "path": "/service-role-setting",
                        "businessCode": "角色設置",
                        "parentId": 115,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    }
                ]
            },
            {
                "id": 118,
                "menName": "企業帳戶",
                "path": "/business",
                "businessCode": "企業帳戶",
                "parentId": 1,
                "isChecked": null,
                "menLevel": 2,
                "subMenuPermissionsVO": [
                    {
                        "id": 119,
                        "menName": "團隊信息",
                        "path": "/business-team",
                        "businessCode": "團隊信息",
                        "parentId": 118,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    },
                    {
                        "id": 120,
                        "menName": "當前服務詳情",
                        "path": "/business-service",
                        "businessCode": "當前服務詳情",
                        "parentId": 118,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    },
                    {
                        "id": 121,
                        "menName": "團隊聯繫人",
                        "path": "/business-contacts",
                        "businessCode": "團隊聯繫人",
                        "parentId": 118,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": []
                    }
                ]
            },
            {
                "id": 122,
                "menName": "設置",
                "path": "/setting",
                "businessCode": "設置",
                "parentId": 1,
                "isChecked": null,
                "menLevel": 2,
                "subMenuPermissionsVO": [
                    {
                        "id": 123,
                        "menName": "系統設置",
                        "path": "/setting-system",
                        "businessCode": "系統設置",
                        "parentId": 122,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": [
                            {
                                "id": 124,
                                "menName": "我的信息",
                                "path": "/setting-userinfo",
                                "businessCode": "我的信息",
                                "parentId": 123,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            },
                            {
                                "id": 125,
                                "menName": "修改密碼",
                                "path": "/setting-change-pwd",
                                "businessCode": "修改密碼",
                                "parentId": 123,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            },
                            {
                                "id": 126,
                                "menName": "通知中心",
                                "path": "/setting-notice",
                                "businessCode": "通知中心",
                                "parentId": 123,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            }
                        ]
                    },
                    {
                        "id": 127,
                        "menName": "在線服務",
                        "path": "/setting-online",
                        "businessCode": "在線服務",
                        "parentId": 122,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": [
                            {
                                "id": 128,
                                "menName": "基礎設置",
                                "path": "/setting-online-base",
                                "businessCode": "基礎設置",
                                "parentId": 127,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            }
                        ]
                    },
                    {
                        "id": 129,
                        "menName": "接入設置",
                        "path": "/setting-join",
                        "businessCode": "接入設置",
                        "parentId": 122,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": [
                            {
                                "id": 130,
                                "menName": "網站接入",
                                "path": "/setting-join-website",
                                "businessCode": "網站接入",
                                "parentId": 129,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            }
                        ]
                    },
                    {
                        "id": 131,
                        "menName": "高級設置",
                        "path": "/setting-advanced",
                        "businessCode": "高級設置",
                        "parentId": 122,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": [
                            {
                                "id": 132,
                                "menName": "短信服務",
                                "path": "/setting-advanced-msg",
                                "businessCode": "短信服務",
                                "parentId": 131,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            },
                            {
                                "id": 133,
                                "menName": "二維碼名片",
                                "path": "/setting-advanced-qrcode",
                                "businessCode": "二維碼名片",
                                "parentId": 131,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "id": 2,
        "menName": "客服模式",
        "path": "customerMode",
        "businessCode": "customer",
        "parentId": 0,
        "isChecked": null,
        "menLevel": 1,
        "subMenuPermissionsVO": [
            {
                "id": 102,
                "menName": "留言",
                "path": "兒",
                "businessCode": "分隔符",
                "parentId": 2,
                "isChecked": null,
                "menLevel": 2,
                "subMenuPermissionsVO": [
                    {
                        "id": 103,
                        "menName": "小計成",
                        "path": "34",
                        "businessCode": "大幅度",
                        "parentId": 102,
                        "isChecked": null,
                        "menLevel": 3,
                        "subMenuPermissionsVO": [
                            {
                                "id": 104,
                                "menName": "76657",
                                "path": "76868",
                                "businessCode": "658568",
                                "parentId": 103,
                                "isChecked": null,
                                "menLevel": 4,
                                "subMenuPermissionsVO": []
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

複製代碼

父組件主要代碼網站

<tree-table :menuData="menuData" :level="1"></tree-table>

// 其中menuData爲後臺返回的數據,level爲菜單層級,在menuData中有返回,這裏主要是用來寫樣式用的。。

複製代碼

子組件組件代碼(一個遞歸組件):ui

子組件所有代碼(說明都在代中有註釋):this

<template>
  <ul class="tree-container" :class="'level'+level">
    <li class="" v-for="(item, Index) in menuData" :key="item.id" :class="'level'+item.menLevel">
      <div class="tree-node-title" :class="'level'+item.menLevel"><label>
        <input type="checkbox" @click.stop="nodeClick(item,Index)" name="menuSelected" :checked="item.isChecked == 1 ? true : false" :value="item.id">
        {{item.menName}}-level{{item.menLevel}}
      </label></div>
      <div class="tree-childnode-container " :class="'level'+item.menLevel">
        <CheckBox :menuData="item.subMenuPermissionsVO" :level="item.menLevel"></CheckBox>
      </div>
    </li>
  </ul>

</template>

<script>
  export default {
    name: 'CheckBox',
    props: ["menuData", "level"],
    data() {
      return {
        checkedVal:[]
      }
    },
    created() {

    },
    mounted() {

    },
    methods: {
      nodeClick(node, index) {
      // 經過isChecked判斷是否爲選中狀態:1-選中;0-未選中。這個字段是後端接口返回的
        if (node.isChecked == 1) {
          this.$set(node, "isChecked", 0)
        } else {
          this.$set(node, "isChecked", 1)
        }
        // 我的理解:組件每次遞歸調用會生成一個實例,this指向這個實例,這些實例相互獨立的,因此每次的this都不同,具體能夠控制檯打印看下。
        this.refreshAllParentNodes(this) // 設置父級狀態
        this.refreshAllSonNodes(this.$children[index], node.isChecked);// 根據當前點擊層級的狀態設置本身全部子級的狀態
      },
      refreshAllSonNodes(node, status) {

        if (node && node.$children.length) {
          node.menuData.map((meunItem, j) => {
            this.$set(meunItem, 'isChecked', status);
            this.refreshAllSonNodes(node.$children[j], status);
          })
        }
      },
      refreshAllParentNodes(node) {
        if (node) {
          var status = 0;
          var nullCount = 0;
          var fullCount = 0;

          if (node.menuData && node.$parent.menuData) {
            node.menuData.map((meunItem, j) => {
              if (typeof meunItem.isChecked == 'undefined') {
                nullCount++
              } else if (meunItem.isChecked == 0) {
                nullCount++
              } else if (meunItem.isChecked == 1) {
                fullCount++
              }
            })
            if (nullCount === node.$children.length) {
            // 該狀態說明當前點擊層級和兄弟層級都沒選中,因此父級也是未選中狀態
              status = 0;
            } else {
            //該狀態說明當前點擊層級和兄弟層級只要有一個選中,父級也是選中狀態
              status = 1;
            }
            node.$parent.menuData.map(child => {
              node.menuData.map((meunItem, j) => {
                if (child.id == meunItem.parentId) {
                // 根據父級id和子級的parentId是否相等,來肯定當前點擊的層級的父級是哪個
                  this.$set(child, 'isChecked', status);
                }
              })

            })
          }
          // 遞歸計算父級
          this.refreshAllParentNodes(node.$parent);
        }
      },
    }
  }
</script>

<style lang="scss">
  .tree-container {
    $borderColor: #ebeef5;
    width: 100%;
    padding: 0;

    &.level3 {
      display: flex;
      flex-wrap: wrap;

      & > .level4 {
        width: 25%;
        padding: 0 20px 0 40px;
      }
    }

    & > .level2 {
      display: flex;
      align-items: center;
      border: 1px solid $borderColor;
      line-height: 45px;

      .tree-node-title {
        &.level2 {
          width: 160px;
          text-align: center;
        }

      }
    }

    .level3 {
      .level3 + .level3 {
        border-top: 1px solid $borderColor;
      }
    }

    .tree-node-title {
      &.level3 {
        background-color: #f2f2f2;
        width: 100%;
        padding: 0 20px;
      }

      &.level1 {
        padding: 20px 0;
      }

    }

    .level2 + .level2 {
      border-top: none;
    }

    .tree-childnode-container {
      width: 100%;

      &.level2 {
        border-left: 1px solid $borderColor;
      }
    }

    input {
      margin-right: 5px;
    }

    label {
      cursor: pointer;
    }

  }
</style>

複製代碼

注意 在當前組件中使用組件自己(遞歸),注意圖中圈出的地方,上面有兩種寫法

0700DC7EBB9A450C8504982D46B291E3.png
相關文章
相關標籤/搜索