1. 递归组件mock数据
App.vue
<template>
<div>
<Tree :data="data"></Tree>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
import Tree from './components/Tree.vue';
interface Tree {
name: string,
checked: boolean,
children?: Tree[]
}
const data = reactive<Tree[]>([
{
name: '1',
checked: true,
children: [
{
name: '1-1',
checked: false
}
]
},
{
name: '2',
checked: true,
},
{
name: '3',
checked: false,
children: [
{
name: '3-1',
checked: false,
children: [
{
name: '3-1-1',
checked: false
},
{
name: '3-1-2',
checked: true
},
],
}
]
},
])
</script>
<style lang="scss" scoped></style>
2. 递归组件定义名称
子组件Tree.vue
<template>
<div class="tree" v-for="item in data">
<input v-model="item.checked" type="checkbox"> <span>{{ item.name }}</span>
// 1.模板自定义名称 直接使用文件名当做递归组件的名称 Tree
<Tree v-if="item?.children?.length" :data="item?.children"></Tree>
</div>
</template>
<script setup lang="ts">
// import { ref,reactive } from 'vue';
interface Tree {
name: string,
checked: false,
children?: Tree[]
}
// // 3.模板自定义名称 利用defineOptions
// defineOptions({
// name: 'nihao'
// })
defineProps<{
data?: Tree[]
}>()
</script>
<!-- // 2.模板自定义名称
<script lang="ts">
//可以将模板中的Tree改名为“nihao”
export default {
name: "nihao"
}
</script> -->
<style lang="scss" scoped>
.tree {
margin-left: 10px;
}
</style>
3. 递归组件处理事件
子组件Tree.vue
<template>
<div @click.stop="clickTap(item,$event)" class="tree" v-for="item in data">
<input v-model="item.checked" type="checkbox"> <span>{{ item.name }}</span>
<Tree v-if="item?.children?.length" :data="item?.children"></Tree>
</div>
</template>
<script setup lang="ts">
// import { ref,reactive } from 'vue';
interface Tree {
name: string,
checked: false,
children?: Tree[]
}
defineProps<{
data?: Tree[]
}>()
const clickTap = (item:Tree,e) => {
console.log(item, e.target);
}
</script>
<style lang="scss" scoped>
.tree {
margin-left: 10px;
}
</style>