The Issue
I've been reading a lot about scoped slots lately, and I havent been able to wrap my head around when to use them and how to implement them. I'd read the docs, think I got it, then when I actually try to implement it...."Fuck! I dont get it!"
Hopefully this straightens some things out for you.
The Skinny
Scoped slots are used when you need access props in the component being rendered for some sort of template modification off of the existing component structure.
Brief Slot Overview
Slots are essentially placeholders were you can place different pieces of DOM content with defaults and names to be explicit about which "slot" you're referring to.
// MyComponent.vue
<template>
<a href="whatever">
<slot>My Default Link Text<slot>
</a>
</template>
// AnotherComponent.vue
<MyComponent>
My New Content
</MyComponent>
Because of the default slot, this will render a link tag with the content My New Content
Scoped Slots
Okay, I've read a lot of articles about scoped slots and seem to always come away pretty confused.
maybe I'm not a good reader, I had a teacher tell me that once....
The Why?
I think its important to ask ourselves a few basic questions when using a new pattern.
Why would I use this and what problem should this solve?
In my personal experience, this gets you pretty far. Sometimes its just a cool pattern that doesn't actually have any business being in your application(yet), because it doesn't solve a specific problem or orients you towards a specific goal.
So....back to scoped slots and the why. From my research and playing with this pattern, what I have come up with is that we use scoped slots when I want to modify the template based on props in the rendered component.
modify the template based on props in the rendered component.
Lets unpack this, shall we.
The How
// MyComponent.vue
<script>
export default {
props: {
name: {
type: String,
default: 'My Default Name',
},
};
<template>
<slot :name="name">
<span>{{ name }}</span>
</slot>
</template>
// AnotherComponent.vue
<template>
<MyComponent />
<template>
We know that AnotherComponent.vue
when used will render a span tag with My Default Name
in the DOM.
There are a few things we need to note before moving on. In MyComponent
, if we know were going to use a scoped slot when rendering, we need to add the prop to the slot, in this case, it would be <slot :name="name">
. If were not going to use a scoped slot, this is not needed!
Note: If we weren't going to use
name
when renderingMyComponent
, we wouldn't add the prop to the slot.
Where scoped slots come in
Stay with me, were almost there.
Up until this point, we have MyComponent
being rendered inside of AnotherComponent
, but, we found out our requirements have changed!
The designer came running over to your desk and said!
"We need a cancel button next to the name"!!!!!
We got this, let's use our scoped slot pattern we just learned!
// AnotherComponent.vue
<template>
<MyComponent>
<template v-slot="{ name }">
<button>Cancel</button>
<span>{{ name }}</span>
</template>
</MyComponent>
</template>
You're probably thinking, "Scott! Why don't we just edit MyComponent
"!?
Thats a great question, MyComponent
could be used in other parts of the application and it would cause us to add arguably too much logic to the component.
So whats happening here?
- We are rendering a template to take place of the default slot, with the
v-slot
directive to destructure the props that are coming fromMyComponent
. - We are rendering the name with a cancel button. Because we cannot access the name in
AnotherComponent
the scoped slot allows us to pull inname
fromMyComponent
.
Pretty straight forward right? Dont believe me? I wouldn't either.......heres a link to a sandbox for you to play around.
Conclusion
So we learned the basic and key aspects of what scoped slots are and when to use them. A few key things to remember.
- When you're using scoped slots, you will be accessing reactive data from the component you are rendering, so make sure its on local state or props.
- Make sure when using scoped slots you pass the props to the slot so you have access to the values.
If you have any questions or want me to cover any additional topics please comment below!
Thanks for reading!
Scott
https://scottistern.com
Top comments (1)
Good article. Thank you for your effort and time.