第一種方式,直接自己調用自己
Tree.vue
<template><div class="tree"><div v-for="(item, index) in data" :key="item.name">每一層 {{ item.name }}<Tree v-if="item?.children?.length" :data='item.children' /></div></div>
</template><script setup lang="ts">
//遞歸的第一種方式 直接引入自己
import Tree from './Tree.vue'
import { TreeList } from '../ts/type'
type Props = {data?: TreeList[]
}
defineProps<Props>();
</script><style scoped>
.tree {margin-left: 20px;border-left: 2px #01847f dashed;
}
</style>
App.vue 里模擬樹形數據,使用遞歸組件
<template><div><Tree :data='data'/></div>
</template><script setup lang="ts">
import Tree from './components/Tree.vue'
import { reactive } from 'vue'
import {TreeList } from './ts/type'
const data = reactive<TreeList[]>([{name: 'no.1',children: [{name: 'no.1-1',children: [{name: 'no.1-1-1',children:[]}]},],}, {name:'no.2'}, {name: 'no.3',children: [{name:'no.3-1'}]}])
</script><style scoped></style>
type.ts 屬性數據的結構
export type TreeList = {name: string //名稱icon?: string //圖標可有可無children?: TreeList[] | [] //子節點 可有可無 還可能傳空數組
}
第二種方式,export 一個name出去
第二種方式 就是像vue2 一樣 export一個name出去
但是setup 語法糖下沒辦法使用 export
我們只需要再定義一個script標簽就可以了
<template><div class="tree"><div v-for="(item, index) in data" :key="item.name">每一層 {{ item.name }}<Tree v-if="item?.children?.length" :data='item.children' /></div></div>
</template><script setup lang="ts">
import { TreeList } from '../ts/type'
type Props = {data?: TreeList[]
}
defineProps<Props>();
</script>
<!-- 第二種方式 就是像vue2 一樣 export一個name出去但是setup 語法糖下沒辦法使用 export 我們只需要再定義一個script標簽就可以了-->
<script lang="ts">
export default {name:'Tree'
}
</script><style scoped>
.tree {margin-left: 20px;border-left: 2px #01847f dashed;
}
</style>
效果圖
我們還可以給樹形遞歸的組件添加參數傳遞事件
要注意在樹形組件的里層也得添加自定義事件
并且這個自定義事件傳的函數很有講究
Tree.vue
<template><div class="tree"><div @click.stop="clickTreeItem(item)" v-for="(item, index) in data" :key="item.name">每一層 {{ item.name }}<Tree @get-tree-item="clickTreeItem" v-if="item?.children?.length" :data='item.children' /><!-- Tree 組件不添加這個自定義事件的話 那么就只有最外層的根節點會向外傳遞數據 --><!-- 注意此處派發的函數clickTreeItem沒有傳item參數了如果傳了就相當于給樹形組件(遞歸組件)的上級派發信息 沒辦法從外部拿到子節點所傳遞的數據了 --><!-- @get-tree-item="clickTreeItem(item)" 寫成這種形式的話 遞歸組件會依次向上層傳遞事件 --><!-- 不傳item的執行結果如下 --><!--子組件派發的item Proxy {name: 'no.1-1-1', children: Array(0)}子組件派發的item Proxy {name: 'no.1-1-1', children: Array(0)}子組件派發的item Proxy {name: 'no.1-1-1', children: Array(0)}父組件得到的item Proxy {name: 'no.1-1-1', children: Array(0)} --><!-- 傳item的執行的結果如下 --><!-- 子組件派發的item Proxy {name: 'no.1-1-1', children: Array(0)}子組件派發的item Proxy {name: 'no.1-1', children: Array(1)}子組件派發的item Proxy {name: 'no.1', children: Array(1)}父組件得到的item Proxy {name: 'no.1', children: Array(1)} --></div></div>
</template><script setup lang="ts">
import { TreeList } from '../ts/type'
type Props = {data?: TreeList[]
}
defineProps<Props>();const emit = defineEmits(['getTreeItem'])
const clickTreeItem=(item:TreeList)=>{console.log('子組件派發的item', item)emit('getTreeItem',item)
}
</script>
<!-- 第二種方式 就是像vue2 一樣 export一個name出去但是setup 語法糖下沒辦法使用 export 我們只需要再定義一個script標簽就可以了-->
<script lang="ts">
export default {name:'Tree'
}
</script><style scoped>
.tree {margin-left: 20px;border-left: 2px #01847f dashed;
}
</style>
App.vue
<template><div><Tree :data='data' @get-tree-item="getTreeItem"/></div>
</template><script setup lang="ts">
import Tree from './components/Tree.vue'
import { reactive } from 'vue'
import {TreeList } from './ts/type'
const data = reactive<TreeList[]>([{name: 'no.1',children: [{name: 'no.1-1',children: [{name: 'no.1-1-1',children:[]}]},],}, {name:'no.2'}, {name: 'no.3',children: [{name:'no.3-1'}]}])const getTreeItem = (item:TreeList) => {console.log('父組件得到的item',item)
}
</script><style scoped></style>