I made a simplified version to propose a solution:
Here as a parent component calling the tree roots:
<template>
<div>
<MyTree v-for="item in records" :key="item.id" :item="item" />
</div>
</template>
<script>
import MyTree from './MyTree';
const FIXTURE = [
{
id: 1,
children: [
{
id: 2,
children: [{id: 3}, {id: 4}, {id: 5}],
},
{
id: 6,
children: [
{id: 7},
{id: 8, children: [{id: 9}, {id: 10}]},
],
},
],
},
{
id: 11,
children: [
{id: 12, children: [{id: 13}, {id: 14}, {id: 15}]},
{id: 16, children: [{id: 17}]},
{id: 18},
],
},
];
export default {
components: {MyTree},
data() {
return {
records: FIXTURE,
};
},
};
</script>
And here is the tree component:
<template>
<div>
<div style="border: 1px solid black; padding: 5px;" :style="offset">
id: {{ item.id }}
// depth: {{ depth }}
// direct: {{ direct }}
// children: {{ childrenCount }}
</div>
<template v-if="item.children">
<MyTree
v-for="record in item.children"
:key="record.id"
:item="record"
:depth="depth + 1"
@born="handleBorn()" />
</template>
</div>
</template>
<script>
const COLORS = [
'white',
'lightgray',
'lightblue',
'lightcyan',
'lightskyblue',
'lightpink',
];
export default {
// MUST give a name in recursive components
// https://vuejs.org/v2/guide/components-edge-cases.html#Recursive-Components
name: 'MyTree',
props: {
item: {type: Object, required: true},
depth: {type: Number, default: 0},
},
data() {
return {
childrenCount: 0,
};
},
computed: {
direct() {
if (Array.isArray(this.item.children)) {
return this.item.children.length;
}
return 0;
},
offset() {
return {
'margin-left': (this.depth * 20) + 'px',
'background-color': COLORS[this.depth % COLORS.length],
};
},
},
mounted() {
this.$emit('born');
},
methods: {
handleBorn() {
this.childrenCount++;
this.$emit('born');
},
},
};
</script>
EDIT
Added screenshot:
