richbai90
richbai90

Reputation: 5204

Accessing children as a prop in a Vue component

This may not be the Vue way to do things, but in React if I wanted to make a FancyList component I could do something like this

const FancyList : React.SFC<{},{}> ({children}) => (
    <ul>
        {...children}
    </ul>
);

const FancyListItem : React.SFC<{text: string}, {}> ({children}) => <li>{...children}</li>

const App = React.SFC<{},{}> () => (
    <FancyList>
        <FancyListItem>foo</FancyListItem>
    <FancyList>
);

This would render a <ul> with <li> children. I am trying to do something similar in Vue, but passing children around doesn't seem to be the thing to do, at least not from what I can see in the documentation. Here is what I have tried in the parent component. I have registered my FancyListItem component to the parent, and to the root. In the parent component the template looks like this

<ul>
  <li v-for child in $root.$children>
</ul>

or this

<ul>
  <li v-for child in children>
</ul>

In the root the template looks like this

<FancyList>
  <FancyListItem>Some Text</FancyListItem>
  <FancyListItem>Some Other Text</FancyListItem>
</FancyList>

In either case I can't get anything to render to the ul.

Upvotes: 1

Views: 821

Answers (2)

Raffobaffo
Raffobaffo

Reputation: 2856

You are right, that's not the Vue way. In vue you would use slots:

This allows you to compose components like this:

<navigation-link url="/profile">
  Your Profile
</navigation-link> 

Then in the template for <navigation-link>, you might have:

<a
  v-bind:href="url"
  class="nav-link"
>
  <slot></slot>
</a>

https://v2.vuejs.org/v2/guide/components-slots.html

Upvotes: 1

Igor Moraru
Igor Moraru

Reputation: 7739

The Vue way of doing this is:

fancyListItem.vue:

<template>
  <li>
     <slot></slot>
  </li>
</template>

fancyList.vue:

<template>
  <ul>
    <slot></slot>
  </ul>
</template>

Root:

<template>
  <fancy-list>
       <fancy-list-item v-for="item in items" :key="item.id">
          {{ item.text }}
       </fancy-list-item>
  </fancy-list>
</template>
<script>
export default {
  components: {
    FancyList: ()=>import('fancyList.vue'),
    FancyListItem: ()=>import('fancyListItem.vue')
  },
  data(){
    return {
      items: [
        //...items
      ]
    }
  }
}
</script>

Upvotes: 1

Related Questions