[Vuejs]-Confirm my understanding of how to iteratively render multiple custom Tree components in Vue.js 3?

0👍

Hmmm. first of all there is a typeo, so f-for should be v-for.

Also, template goes like this:

<template>
  <ul>
    <TreeItem class="item" v-for="(tree, index) in listOfTrees" :model="tree" :key="index"></TreeItem>
  </ul>
</template>

So, iteration goes like this on vue.

Don’t hesitate if you need more explanation.

0👍

You probably should reorganize listOfTrees  using only objects
(simplify the recursion of the component),
(Styles - for example - for a visual demonstration),
but it is for your case:

Tree Component

<template>
<div class="flexCol">
  <template v-for="item in listOfTrees">
     <template v-for="(value, key) in item">
        <div v-if="key === 'name'" class="group">Name: {{value}}</div>
        <template v-else-if="key === 'children'">
           <Menutree :menuPart="value"></Menutree>
        </template>
     </template>
  </template>
</div>
</template>

<script setup>
import {ref} from 'vue'
import Menutree from './Menutree'

const listOfTrees = ref( [{
  name: 'My Tree 2',
  children: [
     {name: 'hello1'},
     {name: 'world1'},
     {
        name: 'child of My Tree 2',
        children: [
           {
              name: 'child 1 of child of My Tree 2',
              children: [{name: 'hello'}, {name: 'world'}]
           },
        ]
     }
  ]
}, {
  name: 'My Tree',
  children: [
     {name: 'hello'},
     {name: 'world'},
     {
        name: 'child of My Tree ',
        children: [
           {
              name: 'child 1  of child of My Tree',
              children: [{name: 'hello'}, {name: 'world'}]
           },
           {name: 'hello'},
           {name: 'world'},
           {
              name: 'child 2  of child of My Tree',
              children: [{name: 'hello'}, {name: 'world'}]
           }
        ]
     }
  ]
}
])
</script>

<style scoped>
.flexCol {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
}
.group {
  width: 10rem;
  text-align: center;
  background-color: #97e6f3;
  padding: 0.25rem 0;
  margin: 0.25rem;
}

</style>

Module - Menutree 
<template>
<div class="flexCol">
  <template v-for="item in menuPart">
     <template v-for="(valueBase, keyBase) in item">
        <div v-if="keyBase === 'name'" style="margin-left: 3rem" 
        class="subGroup">Name: {{valueBase}}</div>
        <template v-else-if="keyBase === 'children'">
           <template v-for="subitem in valueBase">
              <div v-if="subitem['name']" style="margin-left: 6rem" 
              class="subSubGroup">SubName: {{subitem['name']}}</div>
              <Menutree :menuPart="subitem['children']" style="margin- 
               left:6rem; background-color: lightyellow"></Menutree>
           </template>
        </template>
     </template>
  </template>
</div>
</template>

<script setup>
import {ref} from 'vue'

defineProps(['menuPart'])

</script>

<style scoped>
.flexCol {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
}
.subGroup {
  width: auto;
  text-align: left;
  background-color: #f4e1cc;
  padding: 0.25rem;
  margin: 0.25rem 3rem;
}
.subSubGroup {
  width: auto;
  text-align: left;
  background-color: #d6f4cc;
  padding: 0.25rem;
  margin: 0.25rem 6rem;
}
</style>

0👍

Before, I gave an example for the case of unknown nesting of data.
However, if you know for sure that the maximum nesting level is 3 (this is enough for a menu, for example), then everything is generally easier and more convenient for styling and event handling.

<template>
 <div class="flexCol">
  <template v-for="item in listOfTrees">
     <template v-for="(value, key) in item">
        <div v-if="key === 'name'" class="group">Name: {{value}}</div>
        <template v-if="key === 'children' && value.length > 0">
           <template v-for="sub1 in value">
              <div v-if="sub1['name']" style="margin-left: 3rem">Sub1: 
                     {{sub1['name']}}</div>
              <template v-if="sub1['children']?.length > 0">
                 <template v-for="sub2 in sub1['children']">
                    <div v-if="sub2['name']" style="margin-left: 
                        6rem">Sub2: {{sub2['name']}}</div>
                    <template v-if="sub2['children']?.length > 0">
                       <div v-for="sub3 in sub2['children']">
                          <div v-if="sub3['name']" style="margin-left: 
                              9rem">Sub3: {{sub3['name']}}</div>
                       </div>
                    </template>
                 </template>
              </template>
           </template>
        </template>
     </template>
  </template>
 </div>
</template>

Leave a comment