基于vue2 封装树形下拉组件

978 阅读1分钟

基于vue2 封装树形下拉组件

因为项目中的时vant2UI组件库,项目需求中需要实现下拉组织架构功能,翻看vant2文档没有相关的符合的组件,用vue的递归组件实现一个简易的下拉选择框。

采用了递归组件的思路,通过事件每一层子组件触发上一层父组件的事件。

效果图

image-20221004005457490.png

具体代码实现如下:

tree.vue
<template>
  <div>
    <div class="treeTest">
      <childrenItem @CommuEvent="CommuEventFn" v-for="item in treeList" :key="item.id" :list="item" ></childrenItem>
    </div>
  </div>
</template>

<script>
import childrenItem from "@/components/childrenItem.vue";
export default {
  components: {
    childrenItem
  },
  data() {
    return {
      isShow: true,

      treeList: [
        {
          id: "1",
          label: "菜单管理1",
          children: [
            {
              id: "1-1",
              label: "二级菜单1-1",
       
            },
            {
              id: "1-2",
              label: "二级菜单1-2 ",
              children: [
                {
                  id: "1-2-1",
                  label: "三级菜单1-2-1"
                }
              ]
            },
            {
              id: "1-3",
              label: "二级菜单 1-3"
            },
            {
              id: "1-4",
              label: "二级菜单 1-4"
            },
            {
              id: "1-5",
              label: "二级菜单 1-4"
            }
          ]
        },
        {
          id: "2",
          label: "员工管理",
          children: [
            {
              id: "2-1",
              label: "二级员工2-1"
            },
            {
              id: "2-2",
              label: "二级员工2-2"
            },
            {
              id: "2-3",
              label: "二级员工2-3"
            },
            {
              id: "2-4",
              label: "二级员工2-4",
              children: [
                {
                  id: "2-4-1",
                  label: "三级员工"
                }
              ]
            }
          ]
        }
      ]
    };
  },
  methods:{
      active() {
      console.log("触发");
      this.isShow = !this.isShow;
    },

    CommuEventFn(id){
      console.log('91',id);
    }
  }
};
</script>

<style lang="less" scoped>
.treeTest {
  margin: 50px auto;
  padding: 20px;
  // background-color: pink;
  height: 50vh;
  .father {
    .fatherItem {
      // background-color: aqua;
      min-height: 40px;
      .title {
        // background-color: aqua;
        font-size: 20px;
        line-height: 40px;
        display: flex;
        justify-content: space-between;
        align-items: center;
      }

      .children {
        margin-left: 20px;
        .title {
          display: flex;
          justify-content: space-between;
          align-items: center;
        }
      }
    }
  }
}
</style>
childrenItem.vue
<template>
  <div class="container">
    <ul class="children">
      <li class="sonItem"  >
        <div class="title">
          <span @click="selectHandel(list.id)">{{list.label}}</span>
          <van-icon v-show="list.children && !isshow" name="arrow" @click="active" />
          <van-icon v-show="list.children && isshow" @click="active" name="arrow-down" />
        </div>
        <div class="childrenItem" v-show="isshow">
            <childrenItem  @CommuEvent="selectHandel" v-for="item in list.children" :key="item.id" :list="item"></childrenItem>
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
    name:'childrenItem',
  props: {
    list: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      isshow: true
    };
  },
  methods: {
    selectHandel(id) {
    //   console.log(id);
      this.$emit('CommuEvent',id)
    },
    active() {
      console.log("触发");
      this.isshow = !this.isshow;
    }
  }
};
</script>

<style lang="less" scoped>
.children {
  margin-left: 20px;
  .title {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
}
</style>