vue树形组件实现思路

效果图如下:


树形组件效果图

父组件调用树形组件代码:

// menu 要展示菜单的数据
// depth 记录层级的深度,计算文字缩进的像素
// chapterId 传递进来展示默认选中项
// iconUrl 可选,展开折叠图标, 默认是加减号样式
// theme 可选,主题,用来修改样式  menu-catalog-normal

父组件要做的主要步骤:

  1. 引入树形组件
  2. 父组件获取的数据结构如下,把数据处理好后传给树形组件:
{
  "result": [{
      "objectId": "5f97b67697ae1535c05faef1",
      "children": [{
          "objectId": "5f97b87497ae1535c05fafb6",
          "children": [{
            "objectId": "5f97bd5d97ae1535c05fb191",
            "name": "夯实基础"
          }],
          "name": "第1节 空间和时间"
        },
        {
          "objectId": "5f97b88d97ae1535c05fafbc",
          "children": [{
            "objectId": "5f97bd8697ae1535c05fb1aa",
            "name": "夯实基础"
          }],
          "name": "第2节  质点和位移"
        }
      ],
      "name": "第1章   运动的描述"
    },
    {
      "objectId": "5f97b70497ae1535c05faf21",
      "children": [{
        "objectId": "5f97b93397ae1535c05fb002",
        "children": [{
          "objectId": "5f97bdf897ae1535c05fb1f0",
          "name": "夯实基础"
        }],
        "name": "第1节  速度变化规律"
      }],
      "name": "第2章   匀变速直线运动"
    },
    {
      "objectId": "5f97b77f97ae1535c05faf50",
      "children": [{
          "objectId": "5f97b9ed97ae1535c05fb05f",
          "children": [{
            "objectId": "5f97beae97ae1535c05fb27e",
            "children": [{
              "objectId": "5f97beb297ae1535c05fb281",
              "name": "夯实基础"
            }],
            "name": "第1课时  合力与分力"
          }],
          "name": "第1节  科学探究:力的合成"
        },
        {
          "objectId": "5f97b9fd97ae1535c05fb06a",
          "children": [{
            "objectId": "5f97bec197ae1535c05fb28b",
            "name": "夯实基础"
          }],
          "name": "第2节  力得分解"
        }
      ],
      "name": "第3章   力与平衡"
    },
    {
      "objectId": "5f97b7a897ae1535c05faf68",
      "children": [{
        "objectId": "5f97bab697ae1535c05fb0c5",
        "name": "章末检测卷(一)"
      }],
      "name": "章末检测卷"
    }
  ],
  "resultCode": 0,
  "errorCode": -1
}
  1. 主要方法

3-1. 构造数据,给数据添加isOpen开关以及楼层floor

    chapterDataMenuFlag ({val, floor}) {
      if (!(val instanceof Array)) { return false }
      val.map((item, i) => {
        if (item.children) {
          if (i === 0) {
            item.isOpen = true // 默认第一层都是展开状态
          } else {
            item.isOpen = false
          }
          // 判断是第几层
          if (!item.floor) {
            item.floor = `${floor}-${item.objectId}`
          }
          this.chapterDataMenuFlag({val: item.children, floor: item.floor})
        }
      })
      return val
    }

3-2. 渲染后点击展开折叠

    // val是获取到并构造好的数据,checkedData为当前点击项的数据
    menuHandler (val, checkedData) {
      if (!(val instanceof Array)) { return false }
      val.map(item => {
        if (item.children) {
          let currentFloor = checkedData.floor.split('-').pop()
          let totalFloor = checkedData.floor.split('-')
          if (checkedData.floor && currentFloor === item.objectId) {
            // 当前选中的节点进行展开和折叠
            item.isOpen = !checkedData.isOpen
          } else if (checkedData.floor && totalFloor.includes(item.objectId)) {
            // 当前选中的所有父节点都是展开的
            item.isOpen = true
          }
          if (!totalFloor.includes(item.objectId)) {
            // 当前选中的根父节点的相邻节点都折叠
            item.isOpen = false
          }
          this.menuHandler(item.children, checkedData)
        }
      })
    }

3-3. 如果需要展开第一项里最深的一项,并设置

    // 返回最深的一项的id,这个id后面要传递到树形组件当中
    loopForId (val, tempObj) {
      if (!(val instanceof Array)) { return false }
      tempObj = tempObj || {}
      let v = val[0]
      if (v) {
        if (v.children) {
          return this.loopForId(v.children, tempObj)
        } else {
          // 没有children后,保存当前选中的chapterId
          tempObj.chapterId = v.objectId
          tempObj.knowledgeIdToggle = v
        }
      }
      return tempObj
    },

递归树形组件代码







你可能感兴趣的:(vue树形组件实现思路)