模板建站和开发网站区别资源收费网站怎么做
- 该文章是在学习 小满vue3 课程的随堂记录
 - 示例均采用
 <script setup>,且包含typescript的基础用法
一、使用场景
递归组件 的使用场景,如 无限级的菜单 ,接下来就用菜单的例子来学习
二、具体使用
先把菜单的基础内容写出来再说
父组件
<Tree :data="mock" />
 
// 引入子组件
import Tree from "../components/17_组件/Tree.vue";// 菜单的数据格式
interface ITree {name: string;checked: boolean;children?: ITree[];
}
// 数据 mock
const mock: ITree[] = [{name: "1",checked: false,children: [{name: "1-1",checked: true,},],},{name: "2",checked: false,},{name: "3",checked: false,children: [{name: "3-1",checked: false,children: [{name: "3-1-1",checked: true,},],},],},
];
 
子组件
<!-- 第一层数据 -->
<div v-for="item in data" style="margin-left: 16px"><input type="checkbox" v-model="item.checked" />{{ item.name }}
</div>
 
<script setup lang="ts">
// 这里为了方便直接拷贝过来了,实际项目中要抽离出来复用
interface ITree {name: string;checked: boolean;children?: ITree[];
}
// props 定义
defineProps<{data?: ITree[];
}>();
</script>
 
如图,上述代码已经完成了 第一层 菜单数据的渲染:

深层 的菜单数据,就要用到 递归组件 了,递归组件有以下 三种 使用方式
 
1、直接使用 自己的文件名 作为 组件名称,不需要引入
 
当前的文件名称是 Tree.vue,所以直接使用 Tree 即可
子组件
<!-- 第一层数据 -->
<div v-for="item in data" style="margin-left: 16px"><input type="checkbox" v-model="item.checked" />{{ item.name }}<!-- 需要注意:需要按照格式传入子组件要用的数据,并且加上递归的判断条件 --><Tree v-if="item?.children?.length" :data="item.children"></Tree>
</div>
 
使用结果如下:

2、子组件中再定义一个 script,并暴露出 name
子组件
<script lang="ts">
// 再起一个 script(lang必须保持一致),用来定义该组件的 name
export default {name: "TreeVue",
};
</script>
 
使用时,就可以用自定义的组件名
<!-- 第一层数据 -->
<div v-for="item in data" style="margin-left: 16px"><input type="checkbox" v-model="item.checked" />{{ item.name }}<!-- 深层数据 --><TreeVue v-if="item?.children?.length" :data="item.children"></TreeVue>
</div>
 
渲染结果一致:

3、使用 defineOptions 自定义组件名
Vue3.3增加了defineOptions方法,用来定义optionsAPI中的选项,比如组件名称 name(老一点的 vue 版本要装插件才能使用 defineOptions)- 与上面第二种思路一致,就是起个名再用
 
子组件
<script setup lang="ts">
interface ITree {name: string;checked: boolean;children?: ITree[];
}
defineProps<{data?: ITree[];
}>();// 直接在原有的 script 中进行自定义
defineOptions({name: "Self",
});
</script>
 
<!-- 第一层数据 -->
<div v-for="item in data" style="margin-left: 16px"><input type="checkbox" v-model="item.checked" />{{ item.name }}<!-- 深层数据 --><Self v-if="item?.children?.length" :data="item.children"></Self>
</div>
 
渲染结果仍然一致,不再赘述
