vue递归组件怎么使用,手写递归组件tree下拉列表。

递归组件的要求

1、数据的处理,数据一定要子级,也就是children数据,当递归组件的时候将每一项的 children 数据传给递归的组件的数据进行使用。每加一个children就会自动添加一个子级。

2、引入要递归的组件,在它的模板内可以递归地调用自己,不过,只有当它有 name 选项时才可以。一定要设置name属性也就是组件的名字。

3、一定要有递归的终止条件否则会死循环,“max stack size exceeded”的错误,也就是栈溢出。我们可以使用v-if="false"作为递归组件的结束条件。当遇到v-if为false时,组件将不会再进行渲染

4、props一定要和传递组件的属性名字对上。可以设置props默认为数组。

创建一个treeIndex.vue的vue文件,为父组件

<template>
  <div class="">
    <!-- 递归组件将数据传进去 -->
    <Tree  :treeData="treeData"></Tree> 
  </div>
</template>

<script>
import Tree from './tree.vue';
export default {
  data() {
    return {
      treeData: [
        {
          id: 432,
          name: '一级数据-001-111',
          isOpen: false,
          children: [
            {
              id: 32,
              name: '二级数据-002-111',
              isOpen: false,
              children: [
                {
                  id: 532,
                  name: '三级数据-003-111',
                  isOpen: false,
                },
                {
                  id: 5326,
                  name: '三级数据-004-111',
                  isOpen: false,
                },
              ],
            },
            {
              id: 43,
              name: '二级数据-001-111',
              isOpen: false,
              children: [
                {
                  id: 41,
                  name: '三级数据-005-111',
                  isOpen: false,
                },
                {
                  id: 546,
                  name: '三级数据-006-111',
                  isOpen: false,
                },
              ],
            },
          ],
        },
        {
          id: 42143,
          name: '一级数据-007-222',
          isOpen: false,
          children: [
            {
              id: 5235,
              name: '二级数据-008-222',
              isOpen: false,
              children: [
                {
                  id: 5235423,
                  name: '三级数据-009-222',
                  isOpen: false,
                },
                {
                  id: 53252,
                  name: '三级数据-010-222',
                  isOpen: false,
                },
              ],
            },
            {
              id: 457,
              name: '二级数据-011-222',
              isOpen: false,
              children: [
                {
                  id: 5235423,
                  name: '三级数据-012-222',
                  isOpen: false,
                },
                {
                  id: 53252,
                  name: '三级数据-013-222',
                  isOpen: false,
                },
              ],
            },
          ],
        },
      ],
    };
  },
  mounted() {},
  methods: {
  },
  components: { Tree },
};
</script>

<style lang="scss" scoped></style>

在创建一个子组件,也就是我们的递归组件,tree.vue 

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

<script>
import Tree from '@/views/tree/tree.vue';
export default {
  props: {
    treeData: {
      type: Array,
      default: () => [],
    },
  },
  name: 'Tree', // 一定要设置name属性
  data() {
    return {
      newTreeData: [],
    };
  },
  mounted() {
    this.newTreeData = this.treeData;
  },
  methods: {
    openShow(item) {
      this.$nextTick(() => {
        item.isOpen = !item.isOpen; // 重新开启或者关闭
        console.log(item)
      });
    },
  },
  components: { Tree },
};
</script>

<style lang="scss" scoped>
.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 0.5s;
  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
/* .slide-fade-leave-active for below version 2.1.8 */ {
  transform: translateX(10px);
  opacity: 0;
}
</style>

我是刷子哥

猜你喜欢

转载自blog.csdn.net/qq_54753561/article/details/125245177