一个简单的基于vue手写的tree树

本文介绍如何在Vue.js中手动创建一个tree树组件,包括子组件的编写和父组件的调用方法,适用于前端开发人员理解Vue组件化开发。

tree树子组件

<template>
  <ul>
    <li v-for="item in data" :key="item.id">
      <p>
        <span
          v-if="item.children && item.children.length > 0"
          :class="['icon-triangle', item.isOpen ? 'rotate' : 'rotateFalse']"
          @click.stop="openShow(item)"
        ></span>
        <span @click="treeItemClick(item)">{{ item.name }}</span>
      </p>
      <transition name="slide-fade">
        <!-- 递归组件循环引用,要有终止条件,再把子级传进去再次遍历-->
        <myTree
          v-show="item.isOpen && item.children && item.children.length > 0"
          :data="item.children"
          @myTreeClick="myTreeClick"
        ></myTree>
      </transition>
    </li>
  </ul>
</template>

<script>
import myTree from "@/components/myTree.vue";
export default {
  name: "myTree",
  comments: {
    myTree,
  },
  props: {
    // 树形数据
    data: {
      type: Array(),
      default: () => [],
    },
    // 是否手风琴
    isShouFengQin: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {};
  },
  created() {
  },
  methods: {
    openShow(item) {
      this.$nextTick(() => {
        if (this.isShouFengQin) {
          this.treeDataHandle(this.data);
        }
        item.isOpen = !item.isOpen; // 重新开启或者关闭
      });
    },
    // 遍历将tree树全部关闭状态
    treeDataHandle(data) {
      for (let i = 0; i < data.length; i++) {
        if (data[i].children && data[i].children.length > 0) {
          this.treeDataHandle(data[i].children);
        }
        data[i].isOpen = false;
      }
    },
    // 点击事件
    treeItemClick(data) {
      this.$emit("myTreeClick", data);
    },
    myTreeClick(data){
        this.$emit("myTreeClick", data);
    }
  },
};
</script>

<style lang="scss" scoped>
ul li {
  margin-left: -10px;
}
.icon-triangle {
  display: inline-block;
  border: 7px solid transparent;
  border-bottom-color: #ccc;
  transform: rotate(90deg);
  :hover {
    cursor: pointer;
  }
}
li {
  margin-left: 22px;
  margin-top: 13px;
  :hover {
    cursor: pointer;
  }
}
.rotate {
  transform: rotate(180deg);
  transition: all 1s;
  position: relative;
  top: 5px;
  right: 5px;
}
.rotateFalse {
  transform: rotate(90deg);
  transition: all 0.2s;
}

.slide-fade-enter-active {
  transition: all 0.3s ease;
}
.slide-fade-leave-active {
  transition: all 0.2s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter,
.slide-fade-leave-to {
  transform: translateX(10px);
  opacity: 0;
}
</style>

父组件调用

<template>
  <div id="app">
    <my-tree :data="treeData" @myTreeClick="myTreeClick"></my-tree>
  </div>
</template>

<script>
import MyTree from "./components/myTree.vue";
export default {
  name: "App",
  components: {
    MyTree,
  },
  data() {
    return {
      // n1:1
      treeData: [
        {
          id: 1,
          name: "一级数据",
          isOpen: false,
          isChecked: false,
          children: [
            {
              id: 10,
              name: "二级数据",
              isOpen: false,
              isChecked: false,
              children: [
                {
                  id: 100,
                  name: "三级数据",
                  isOpen: false,
                  isChecked: false,
                  children: [
                    {
                      id: 1000,
                      name: "四级数据",
                      isOpen: false,
                      isChecked: false,
                    },
                  ],
                },
              ],
            },
          ],
        },
        {
          id: 2,
          name: "一级数据",
          isOpen: false,
          isChecked: false,
          children: [
            {
              id: 21,
              name: "二级数据",
              isOpen: false,
              isChecked: false,
            },
          ],
        },
      ],
    };
  },
  methods: {
    myTreeClick(data) {
      console.log(data);
    },
  },
};
</script>

<style>
ul,
li {
  list-style: none;
}
</style>



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值