vue封装自定义树形组件

132 阅读1分钟

tt-one.webp

父组件

<template>
  <div>
    <treeItem :list="data"/>    
  </div>
</template>

<script>
import treeItem from "@/components/treeItem"
 export default {
    data() {
      return {
        data: [],
      }
    },
    components:{
      treeItem
    },
    created(){
      this.asyncData()
    },
    methods: {
     async asyncData(){
        // 模拟后台数据
        const res = await new Promise((resolve) => {
          setTimeout(() => {
            resolve(
            [
              { id: 2, name: '总部', parentId: 1},
              { id: 3, name: '开发部', parentId: 2},
              { id: 4, name: '财务部', parentId: 2},
              { id: 5, name: '人事部', parentId: 2},
              { id: 6, name: '其他部门', parentId: 4},
            ]
          )
          }, 0);
        })
        // 将结果赋值给data
        this.data = this.treeToArray(res)
      },
      // 核心思路就是 parentId === id 那么就是 id下面的children
      treeToArray(arr, parentId=1){
        let result = []
        arr.forEach(item => {
          if(item.parentId === parentId){
            const children = this.treeToArray(arr,item.id)
            if(children && children.length){
              item.children = children
            }
            result.push(item)
          }
        })
        return result
      }
    }
  }
</script>

子组件(treeItem)

<template>
  <div>
    <div v-for="item in list" :key="item.id" >
      <!-- 点击显示下面的孩子们 -->
      <div @click="change(item)">{{ item.name }}</div>
      <div v-if="item.children && flag" class="item-children">
        <!-- 递归自己的组件,将层级数据展示出来 -->
        <treeItem :list="item.children"></treeItem>
      </div>
    </div>
  </div>
</template>

<script>
  export default{
    // 递归组件必须要写 name 属性
    name:'TreeItem',
    data(){
      return {
        flag: false
      }
    },
    props:{
      list: {
        type: Array
      }
    },
    methods:{
      // 点击每一项显示 自己孩子们
      change(item){
        if(item.children){
          this.flag = true
        }
      }
    }
  }
</script>

<style scoped>
.item-children{
  margin-left: 20px;
}
</style>