HSLM
HSLM

Reputation: 2022

Vue js v3 component does not have access to $children anymore. How can we get a component children?

With Vue 2, we could use this.$children to get all the children components in the component slot. But with Vue 3 this is not possible anymore. And I couldn't find anything about an alternative or a workaround!

So, can anyone help with that? :)

What I want to achieve is:

To have a component with let's say name TabsView

And I want to use it like this:

<tabs-view>
  <tabs-title target="tab1">Title1</tabs-title>
  <tab-content name="tab1">...</tab-content>

  <tabs-title target="tab2">Title2</tabs-title>
  <tab-content name="tab2">...</tab-content>
<tabs-view>

And I want all the logic inside the TabsView component. So that is why I want to get the $children within it. So I can build the tabs using the values of the children components.

Because I will use the same to build tabs in different many places. And I don't want to copy the logic with refs. unless there is a way to do that with refs without moving the same logic to every place I use the component

Upvotes: 4

Views: 2045

Answers (1)

Daniel
Daniel

Reputation: 35694

You can either use this.$el.parentElement.children to get the DOM elements, but that won't give you the components. this: this.$.subTree.children will give you the children, which will include DOM elements and the components.

But this functionality is likely kept hidden for a reason, so if @Guillaume F wants you to consider an alternate solution, I'd heed his advice.

example:

const app = Vue.createApp({
  data() {
    return {
      color: null
    }
  },
  mounted() {
    const children = this.$.subTree.children
    console.log(children.map(c => c.type))
  }
})

app.component('tabs-title', {
  template: '<h1>TITLE: <slot></slot></h1>'
})
app.component('tab-content', {
  template: '<p>TAB: <slot></slot></p>'
})

app.mount('#app')
<script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
<div id="app">
  <tabs-title target="tab1">Title1</tabs-title>
  <tab-content name="tab1">...</tab-content>

  <hr/> <!-- will return string as type -->
  <tabs-title target="tab2">Title2</tabs-title>
  <tab-content name="tab2">...</tab-content>
</div>

Upvotes: 2

Related Questions