1. 递归组件

递归组件是指内部包含自己的组件,这种组件在开发中非常有用。在Vue3中使用递归组件非常简单,只需要在组件的template中调用自身即可。

1.1. 基本使用

下面是一个递归组件的例子:

<!-- RecurtionComponent.vue -->
<template>
  <div>
    <ul>
      <!-- 调用组件,并绑定数据 -->
      <Tree :data="treeData"></Tree>
    </ul>
  </div>
</template>
<script lang="ts" setup>
// 导入递归组件
import Tree from "./components/Tree.vue";
import { ref } from "vue";

// 需要实现递归的数据
const treeData = ref({
  label: "1-1",
  id: 1,
  children: [
    {
      label: "1-1-1",
      id: 2,
    },
    {
      label: "1-1-2",
      id: 3,
      children: [
        {
          label: "1-1-2-1",
          id: 4,
        },
        {
          label: "1-1-2-2",
          id: 5,
        },
      ],
    },
    {
      label: "1-1-3",
      id: 6,
      children: [
        {
          label: "1-1-3-1",
          id: 7,
          children: [
            {
              label: "1-1-3-1-1",
              id: 8,
            },
            {
              label: "1-1-3-1-2",
              id: 9,
            },
            {
              label: "1-1-3-1-3",
              id: 10,
            },
          ],
        },
        {
          label: "1-1-3-2",
          id: 11,
          children: [
            {
              label: "1-1-3-2-1",
              id: 12,
            },
            {
              label: "1-1-3-2-2",
              id: 13,
            },
          ],
        },
        {
          label: "1-1-3-3",
          id: 4,
        },
      ],
    },
  ],
});
</script>

在上面的代码中,我们创建了一个名为RecursiveComponent的组件,它包含一个ul元素和一个递归调用的子组件 Tree。在子组件中,我们使用v-if判断当前节点是否有子节点,如果有则递归调用自身,直到到达叶子节点。这样就可以实现无限级别的树形结构。需要注意的是,为了避免无限递归,我们需要在递归调用时传递一个子节点的数据,而不是整个数据对象。

1.2. 注意事项

  • 递归组件必须有 name 属性,指定 name 选项的好处是便于调试。有名字的组件有更友好的警告信息,在有 vue-devtools,未命名组件将显示成 <AnonymousComponent>
  • Vue3 在全局用 Vue.component() 注册时,全局 ID 自动作为组件的 name。

下面是 Tree 组件的代码:

<!-- Tree.vue -->
<template>
  <li>
    <!-- 点击折叠展开 -->
    <div @click="toggle">
      <!-- 判断是否有子节点,有的话显示折叠展开的图标,如果没有下级目录的话,则不显示 -->
      <span v-if="isFolder">{{ open ? "-" : "+" }}</span>
      <!-- 显示内容 -->
      {{ data.label }}
    </div>
    <!-- 判断是否有子节点,有的话控制是否显示下级目录 -->
    <ul v-show="open" v-if="isFolder">
      <!-- 重点代码,调用自身,实现递归,绑定数据 -->
      <Tree v-for="item in data.children" :data="item" :key="item.label"></Tree>
    </ul>
  </li>
</template>

<script lang="ts">
export default {
  name: "Tree",
};
</script>

<script lang="ts" setup>
import { ref, computed } from "vue";

// 接收父组件传递的数据,递归时传递 children
const props = defineProps({
  data: {
    type: Object,
    required: true,
  },
});

// 默认不显示下级目录
const open = ref(false);

// 控制是否有下级目录和显示下级目录
const isFolder = computed(() => props.data?.children?.length);

// 点击折叠展开的方法
const toggle = () => {
  if (isFolder) {
    open.value = !open.value;
  }
};
</script>

1.3. 效果展示

在这里插入图片描述

2. 总结

在 Vue3 中使用递归组件非常简单,只需要在组件的 template 中调用自身即可。递归组件在开发中非常有用,可以帮助我们处理无限级别的树形结构等复杂场景。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐