Professional Documents
Culture Documents
<div id="app">
<products-list :products="products"></products-list>
</div>
<script src="vue.js"></script>
<script>
Vue.component('products-list', {
props: {
products: {
type: Array,
required: true
}
},
template: `
<ul>
<li v-for="product in products">
{{ product.name }}
</li>
</ul>
`
})
new Vue({
el: '#app',
data: {
products: [{
name: 'Magnifying Glass',
image: 'magnify.png'
}, {
name: 'Light Bulb',
image: 'bulb.png'
}]
}
})
</script>
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 1/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
<div id="app">
<products-list :products="products"></products-list>
<products-list :products="products" :show-image="true">
</products-list>
</div>
<script src="vue.js"></script>
<script>
Vue.component('products-list', {
props: {
products: {
type: Array,
required: true
},
showImage: {
type: Boolean,
default: false
}
},
template: `
<ul>
<li v-for="product in products">
<img v-show="showImage" :src="product.image" />
{{ product.name }}
</li>
</ul>
`
})
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 2/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
Notice how we’re using a new prop called showImage , which if true shows the product image. This
would display:
<div id="app">
<products-list :products="products"></products-list>
<products-list :products="products">
<template slot="product" slot-scope="slotProps">
<img :src="slotProps.product.image" /> {{
slotProps.product.name.toUpperCase() }}
</template>
</products-list>
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 3/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
</div>
<script src="vue.js"></script>
<script>
Vue.component('products-list', {
props: {
products: {
type: Array,
required: true
}
},
template: `
<ul>
<li v-for="product in products">
<slot name="product" :product="product" >
{{ product.name }}
</slot>
</li>
</ul>`
})
new Vue({ ... Same as above ... })
</script>
First notice <slot name="product" :product="product" > , this is being created like a
normal slot, but it also has product as a slotProp . This slotProp can get accessed by the
parent if the parent wants to override what gets displayed by default in the slot, which in this case
is {{ product.name }} .
The parent can write out markup to get displayed inside the slot by writing <template
slot="product" slot-scope="slotProps"> . Inside the slotProps parameter the value is
first { "product": { "name": "Magnifying Glass", "image": "magnify.png" }
} and then it is { "product": { "name": "Light Bulb", "image": "bulb.png" } } ,
the two values inside the products array. As you might expect, this displays:
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 4/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
Destructuring
It’s worth noting at this point that we can use destructuring to make using slotProps a little more
readable. So instead of writing:
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 5/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
As you can see, this sort of pattern can be used for all sorts of reusable functionality.
<div id="app">
<products-list :products="products"></products-list>
</div>
<script src="vue.js"></script>
<script>
Vue.component('products-list', {
props: {
products: {
type: Array,
required: true
}
},
render(h) { // <-- Notice our render function
return h('ul', [
this.products.map(product =>
h('li', [product.name])
)
])
}
})
new Vue({ ... Same as above ... })
</script>
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 6/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
If you’re not familiar with render functions yet, I highly recommend you go watch lesson 4 of this
course where we explain template compilation.
To use Render props as a technique to solve our problem, we will be literally sending in a render
function as a prop into our component. See below:
<div id="app">
<products-list :products="products"></products-list>
<products-list :products="products" :product-
renderer="imageRenderer"></products-list>
</div>
<script src="vue.js"></script>
<script>
Vue.component('products-list', {
props: {
products: {
type: Array,
required: true
},
productRenderer: { // <-- Here's our new prop
type: Function,
default (h, product) { // <-- By default just print the
name
return product.name
}
}
},
render(h) {
return h('ul', [
this.products.map(product =>
h('li', [this.productRenderer(h, product)]) // use our
new prop
)
])
}
})
new Vue({
el: '#app',
data: {
products: [{
name: 'Magnifying Glass',
image: 'magnify.png'
}, {
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 7/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
Notice my comments above, and then notice how I call the component: <products-list
:products="products" :product-renderer="imageRenderer"></products-list> .
Here I’m passing in the imageRenderer that I declare in the root element.
If I wanted to clean this up a little I could use the JSX babel plugin, which would allow me to write JSX
inside of my render functions. It’ll feel much more React like, if that’s something you enjoy. 😉
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 8/9
19/4/2020 Scoped Slots & Render Props - Advanced Components | Vue Mastery
If we look inside the readme, we find that we can pass in a renderSuggestion method to this
component library to specify the way your suggestions are displayed. It even shows you the JSX
syntax:
Let’s ReVue
If you’ve never seen either of these patterns before, you might be wondering why you wouldn’t always
use Scoped Slots. In my opinion (and Evan You’s) Scoped Slots is definitely the more Vue friendly
solution. However, I’m sure there are some cases where you may need the extra power of Render
Props, or if you’re using JSX with render functions.
Both Scoped Slots and Render Props allow the parent component to control how the child’s data is
displayed, which can help you create reusable and maintainable components.
Next Lesson
On our next lesson we’ll be talking with Evan You, the creator of Vue.js, about advanced Vue.js
components.
https://www.vuemastery.com/courses/advanced-components/render-props-scoped-slots 9/9