Reputation: 5204
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
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
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