You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> This page assumes you've already read the [Components Basics](/guide/essentials/component-basics). Read that first if you are new to components.
4
8
5
-
## Slot Content
9
+
## Slot Content and Outlet
6
10
7
-
Vue implements a content distribution API inspired by the [Web Components spec draft](https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Slots-Proposal.md), using the `<slot>` element to serve as distribution outlets for content.
11
+
We have learned that components can accept props, which can be JavaScript values of any type. But how about template content? In some cases, we may want to pass a template fragment to a child component, and let the child component render the fragment within its own template.
8
12
9
-
This allows you to compose components like this:
13
+
For example, we may have a `<FancyButton>` component that supports usage like this:
10
14
11
-
```vue-html
12
-
<todo-button>
13
-
Add todo
14
-
</todo-button>
15
+
```vue-html{2}
16
+
<FancyButton>
17
+
Click me! <!-- slot content -->
18
+
</FancyButton>
15
19
```
16
20
17
-
Then in the template for`<todo-button>`, you might have:
21
+
This is how the template of`<FancyButton>` looks like:
18
22
19
-
```vue-html
20
-
<!-- todo-button component template -->
21
-
<button class="btn-primary">
22
-
<slot></slot>
23
+
```vue-html{2}
24
+
<button class="fancy-btn">
25
+
<slot></slot> <!-- slot outlet -->
23
26
</button>
24
27
```
25
28
26
-
When the component renders, `<slot></slot>` will be replaced by "Add Todo".
29
+
Notice the `<slot>` element, which is a **slot outlet** that indicates where the parent-provided **slot content** should be rendered.
27
30
28
-
```vue-html
29
-
<!-- rendered HTML -->
30
-
<button class="btn-primary">
31
-
Add todo
32
-
</button>
33
-
```
31
+

34
32
35
-
Strings are just the beginning though! Slots can also contain any template code, including HTML:
33
+
And the final rendered DOM:
36
34
37
-
```vue-html
38
-
<todo-button>
39
-
<!-- Add a Font Awesome icon -->
40
-
<i class="fas fa-plus"></i>
41
-
Add todo
42
-
</todo-button>
35
+
```html
36
+
<buttonclass="fancy-btn">Click me!</button>
43
37
```
44
38
45
-
Or even other components:
39
+
With slots, the `<FancyButton>` is responsible for rendering the outer `<button>` (and its fancy styling), while the inner content is determined by the parent component using `<FancyButton>`. This makes our `<FancyButton>` more flexible and reusable, since we can now use it in different places with different inner content, but all with the same fancy styling.
If `<todo-button>`'s template did **not** contain a `<slot>` element, any content provided between its opening and closing tag would be discarded.
41
+
Slot content is not just limited to text. It can be any valid template content. For example, we can pass in elements or even other components:
56
42
57
43
```vue-html
58
-
<!-- todo-button component template -->
59
-
60
-
<button class="btn-primary">
61
-
Create a new item
62
-
</button>
44
+
<FancyButton>
45
+
<span style="color:red">Click me!</span>
46
+
<AwesomeIcon name="plus" />
47
+
</FancyButton>
63
48
```
64
49
65
-
```vue-html
66
-
<todo-button>
67
-
<!-- Following text won't be rendered -->
68
-
Add todo
69
-
</todo-button>
70
-
```
50
+
<divclass="composition-api">
71
51
72
-
## Render Scope
52
+
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCBGYW5jeUJ1dHRvbiBmcm9tICcuL0ZhbmN5QnV0dG9uLnZ1ZSdcbmltcG9ydCBBd2Vzb21lSWNvbiBmcm9tICcuL0F3ZXNvbWVJY29uLnZ1ZSdcbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxGYW5jeUJ1dHRvbj5cbiAgICBDbGljayBtZVxuIFx0PC9GYW5jeUJ1dHRvbj5cblxuICA8RmFuY3lCdXR0b24+XG4gICAgPHNwYW4gc3R5bGU9XCJjb2xvcjpyZWRcIj5DbGljayBtZSE8L3NwYW4+XG4gICAgPEF3ZXNvbWVJY29uIC8+XG4gIDwvRmFuY3lCdXR0b24+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0iLCJGYW5jeUJ1dHRvbi52dWUiOiI8dGVtcGxhdGU+XG4gIDxidXR0b24gY2xhc3M9XCJmYW5jeS1idG5cIj5cbiAgXHQ8c2xvdC8+XG5cdDwvYnV0dG9uPlxuPC90ZW1wbGF0ZT5cblxuPHN0eWxlPlxuLmZhbmN5LWJ0biB7XG4gIGNvbG9yOiAjZmZmO1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMzE1ZGVnLCAjNDJkMzkyIDI1JSwgIzY0N2VmZik7XG4gIGJvcmRlcjogbm9uZTtcbiAgcGFkZGluZzogMTBweDtcbiAgYm9yZGVyLXJhZGl1czogOHB4O1xufVxuPC9zdHlsZT4iLCJBd2Vzb21lSWNvbi52dWUiOiI8IS0tIHVzaW5nIGFuIGVtb2ppIGp1c3QgZm9yIGRlbW8gcHVycG9zZXMgLS0+XG48dGVtcGxhdGU+4p6VPC90ZW1wbGF0ZT4ifQ==)
73
53
74
-
When you want to use data inside a slot, such as in:
54
+
</div>
55
+
<divclass="options-api">
75
56
76
-
```vue-html
77
-
<todo-button>
78
-
Delete a {{ item.name }}
79
-
</todo-button>
80
-
```
57
+
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdD5cbmltcG9ydCBGYW5jeUJ1dHRvbiBmcm9tICcuL0ZhbmN5QnV0dG9uLnZ1ZSdcbmltcG9ydCBBd2Vzb21lSWNvbiBmcm9tICcuL0F3ZXNvbWVJY29uLnZ1ZSdcbiAgXG5leHBvcnQgZGVmYXVsdCB7XG4gIGNvbXBvbmVudHM6IHsgRmFuY3lCdXR0b24sIEF3ZXNvbWVJY29uIH1cbn1cbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxGYW5jeUJ1dHRvbj5cbiAgICBDbGljayBtZVxuIFx0PC9GYW5jeUJ1dHRvbj5cblxuICA8RmFuY3lCdXR0b24+XG4gICAgPHNwYW4gc3R5bGU9XCJjb2xvcjpyZWRcIj5DbGljayBtZSE8L3NwYW4+XG4gICAgPEF3ZXNvbWVJY29uIC8+XG4gIDwvRmFuY3lCdXR0b24+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0iLCJGYW5jeUJ1dHRvbi52dWUiOiI8dGVtcGxhdGU+XG4gIDxidXR0b24gY2xhc3M9XCJmYW5jeS1idG5cIj5cbiAgXHQ8c2xvdC8+XG5cdDwvYnV0dG9uPlxuPC90ZW1wbGF0ZT5cblxuPHN0eWxlPlxuLmZhbmN5LWJ0biB7XG4gIGNvbG9yOiAjZmZmO1xuICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMzE1ZGVnLCAjNDJkMzkyIDI1JSwgIzY0N2VmZik7XG4gIGJvcmRlcjogbm9uZTtcbiAgcGFkZGluZzogMTBweDtcbiAgYm9yZGVyLXJhZGl1czogOHB4O1xufVxuPC9zdHlsZT4iLCJBd2Vzb21lSWNvbi52dWUiOiI8IS0tIHVzaW5nIGFuIGVtb2ppIGp1c3QgZm9yIGRlbW8gcHVycG9zZXMgLS0+XG48dGVtcGxhdGU+4p6VPC90ZW1wbGF0ZT4ifQ==)
58
+
59
+
</div>
81
60
82
-
That slot has access to the same instance properties (i.e. the same "scope") as the rest of the template.
61
+
Vue components' slot mechanism is inspired by the [native Web Component `<slot>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot), but with additional capabilities that we will see later.
The slot does **not** have access to `<todo-button>`'s scope. For example, trying to access `action` would not work:
65
+
Slot content has access to the data scope of the parent component, because it is defined in the parent. For example:
87
66
88
67
```vue-html
89
-
<todo-button action="delete">
90
-
Clicking here will {{ action }} an item
91
-
<!--
92
-
The `action` will be undefined, because this content is passed
93
-
_to_ <todo-button>, rather than defined _inside_ the
94
-
<todo-button> component.
95
-
-->
96
-
</todo-button>
68
+
<span>{{ message }}</span>
69
+
<FancyButton>{{ message }}</FancyButton>
97
70
```
98
71
99
-
As a rule, remember that:
72
+
Here both <spanv-pre>`{{ message }}`</span> interpolations will render the same content, even though one of them is passed into a child component.
73
+
74
+
Slot content does **not** have access to the child component's data. As a rule, remember that:
100
75
101
76
> Everything in the parent template is compiled in parent scope; everything in the child template is compiled in the child scope.
102
77
103
78
## Fallback Content
104
79
105
-
There are cases when it's useful to specify fallback (i.e. default) content for a slot, to be rendered only when no content is provided. For example, in a `<submit-button>` component:
80
+
There are cases when it's useful to specify fallback (i.e. default) content for a slot, to be rendered only when no content is provided. For example, in a `<SubmitButton>` component:
106
81
107
82
```vue-html
108
83
<button type="submit">
@@ -112,45 +87,52 @@ There are cases when it's useful to specify fallback (i.e. default) content for
112
87
113
88
We might want the text "Submit" to be rendered inside the `<button>` most of the time. To make "Submit" the fallback content, we can place it in between the `<slot>` tags:
114
89
115
-
```vue-html
90
+
```vue-html{3}
116
91
<button type="submit">
117
-
<slot>Submit</slot>
92
+
<slot>
93
+
Submit <!-- fallback content -->
94
+
</slot>
118
95
</button>
119
96
```
120
97
121
98
Now when we use `<submit-button>` in a parent component, providing no content for the slot:
122
99
123
100
```vue-html
124
-
<submit-button></submit-button>
101
+
<SubmitButton />
125
102
```
126
103
127
-
will render the fallback content, "Submit":
104
+
This will render the fallback content, "Submit":
128
105
129
-
```vue-html
130
-
<button type="submit">
131
-
Submit
132
-
</button>
106
+
```html
107
+
<buttontype="submit">Submit</button>
133
108
```
134
109
135
110
But if we provide content:
136
111
137
112
```vue-html
138
-
<submit-button>
139
-
Save
140
-
</submit-button>
113
+
<SubmitButton>Save</SubmitButton>
141
114
```
142
115
143
116
Then the provided content will be rendered instead:
144
117
145
-
```vue-html
146
-
<button type="submit">
147
-
Save
148
-
</button>
118
+
```html
119
+
<buttontype="submit">Save</button>
149
120
```
150
121
122
+
<divclass="composition-api">
123
+
124
+
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCBTdWJtaXRCdXR0b24gZnJvbSAnLi9TdWJtaXRCdXR0b24udnVlJ1xuPC9zY3JpcHQ+XG5cbjx0ZW1wbGF0ZT5cbiAgPCEtLSB1c2UgZmFsbGJhY2sgdGV4dCAtLT5cbiAgPFN1Ym1pdEJ1dHRvbiAvPlxuICBcbiAgPCEtLSBwcm92aWRlIGN1c3RvbSB0ZXh0IC0tPlxuICA8U3VibWl0QnV0dG9uPlNhdmU8L1N1Ym1pdEJ1dHRvbj5cbjwvdGVtcGxhdGU+IiwiaW1wb3J0LW1hcC5qc29uIjoie1xuICBcImltcG9ydHNcIjoge1xuICAgIFwidnVlXCI6IFwiaHR0cHM6Ly9zZmMudnVlanMub3JnL3Z1ZS5ydW50aW1lLmVzbS1icm93c2VyLmpzXCJcbiAgfVxufSIsIlN1Ym1pdEJ1dHRvbi52dWUiOiI8dGVtcGxhdGU+XG4gIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiPlxuXHQgIDxzbG90PlxuICAgIFx0U3VibWl0IDwhLS0gZmFsbGJhY2sgY29udGVudCAtLT5cbiAgXHQ8L3Nsb3Q+XG5cdDwvYnV0dG9uPlxuPC90ZW1wbGF0ZT4ifQ==)
125
+
126
+
</div>
127
+
<divclass="options-api">
128
+
129
+
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdD5cbmltcG9ydCBTdWJtaXRCdXR0b24gZnJvbSAnLi9TdWJtaXRCdXR0b24udnVlJ1xuICBcbmV4cG9ydCBkZWZhdWx0IHtcbiAgY29tcG9uZW50czoge1xuICAgIFN1Ym1pdEJ1dHRvblxuICB9XG59XG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8IS0tIHVzZSBmYWxsYmFjayB0ZXh0IC0tPlxuICA8U3VibWl0QnV0dG9uIC8+XG4gIFxuICA8IS0tIHByb3ZpZGUgY3VzdG9tIHRleHQgLS0+XG4gIDxTdWJtaXRCdXR0b24+U2F2ZTwvU3VibWl0QnV0dG9uPlxuPC90ZW1wbGF0ZT4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL3NmYy52dWVqcy5vcmcvdnVlLnJ1bnRpbWUuZXNtLWJyb3dzZXIuanNcIlxuICB9XG59IiwiU3VibWl0QnV0dG9uLnZ1ZSI6Ijx0ZW1wbGF0ZT5cbiAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCI+XG5cdCAgPHNsb3Q+XG4gICAgXHRTdWJtaXQgPCEtLSBmYWxsYmFjayBjb250ZW50IC0tPlxuICBcdDwvc2xvdD5cblx0PC9idXR0b24+XG48L3RlbXBsYXRlPiJ9)
130
+
131
+
</div>
132
+
151
133
## Named Slots
152
134
153
-
There are times when it's useful to have multiple slots. For example, in a `<base-layout>` component with the following template:
135
+
There are times when it's useful to have multiple slot outlets in a single component. For example, in a `<BaseLayout>` component with the following template:
154
136
155
137
```vue-html
156
138
<div class="container">
@@ -184,28 +166,40 @@ For these cases, the `<slot>` element has a special attribute, `name`, which can
184
166
185
167
A `<slot>` outlet without `name` implicitly has the name "default".
186
168
187
-
To provide content to named slots, we need to use the `v-slot` directive on a `<template>` element, providing the name of the slot as `v-slot`'s argument:
169
+
In a parent component using `<BaseLayout>`, we need a way to pass multiple slot content framgents, each targeting a different slot outlet. This is where the `v-slot` directive comes in.
170
+
171
+
`v-slot` must be used on a `<template>`, where it expects an argument correspnding to its target slot's name:
188
172
189
173
```vue-html
190
-
<base-layout>
174
+
<BaseLayout>
191
175
<template v-slot:header>
176
+
<!-- content for the header slot -->
177
+
</template>
178
+
</BaseLayout>
179
+
```
180
+
181
+
`v-slot` has a dedicated shorthand `#`, so `<template v-slot:header>` can be shortened to just `<template #header>`. It means "render this template fragment in the child component's 'header' slot".
182
+
183
+
Here's us passing content to all three slots to `<BaseLayout>` using the shorthand syntax:
184
+
185
+
```vue-html
186
+
<BaseLayout>
187
+
<template #header>
192
188
<h1>Here might be a page title</h1>
193
189
</template>
194
190
195
-
<template v-slot:default>
191
+
<template #default>
196
192
<p>A paragraph for the main content.</p>
197
193
<p>And another one.</p>
198
194
</template>
199
195
200
-
<template v-slot:footer>
196
+
<template #footer>
201
197
<p>Here's some contact info</p>
202
198
</template>
203
-
</base-layout>
199
+
</BaseLayout>
204
200
```
205
201
206
-
Now everything inside the `<template>` elements will be passed to the corresponding slots.
207
-
208
-
The rendered HTML will be:
202
+
Now everything inside the `<template>` elements will be passed to the corresponding slots. The final rendered HTML will be:
209
203
210
204
```vue-html
211
205
<div class="container">
@@ -222,11 +216,47 @@ The rendered HTML will be:
222
216
</div>
223
217
```
224
218
219
+
<divclass="composition-api">
220
+
221
+
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cD5cbmltcG9ydCBCYXNlTGF5b3V0IGZyb20gJy4vQmFzZUxheW91dC52dWUnXG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8QmFzZUxheW91dD5cbiAgICA8dGVtcGxhdGUgI2hlYWRlcj5cbiAgICAgIDxoMT5IZXJlIG1pZ2h0IGJlIGEgcGFnZSB0aXRsZTwvaDE+XG4gICAgPC90ZW1wbGF0ZT5cblxuICAgIDx0ZW1wbGF0ZSAjZGVmYXVsdD5cbiAgICAgIDxwPkEgcGFyYWdyYXBoIGZvciB0aGUgbWFpbiBjb250ZW50LjwvcD5cbiAgICAgIDxwPkFuZCBhbm90aGVyIG9uZS48L3A+XG4gICAgPC90ZW1wbGF0ZT5cblxuICAgIDx0ZW1wbGF0ZSAjZm9vdGVyPlxuICAgICAgPHA+SGVyZSdzIHNvbWUgY29udGFjdCBpbmZvPC9wPlxuICAgIDwvdGVtcGxhdGU+XG4gIDwvQmFzZUxheW91dD5cbjwvdGVtcGxhdGU+IiwiaW1wb3J0LW1hcC5qc29uIjoie1xuICBcImltcG9ydHNcIjoge1xuICAgIFwidnVlXCI6IFwiaHR0cHM6Ly9zZmMudnVlanMub3JnL3Z1ZS5ydW50aW1lLmVzbS1icm93c2VyLmpzXCJcbiAgfVxufSIsIkJhc2VMYXlvdXQudnVlIjoiPHRlbXBsYXRlPlxuICA8ZGl2IGNsYXNzPVwiY29udGFpbmVyXCI+XG4gICAgPGhlYWRlcj5cbiAgICAgIDxzbG90IG5hbWU9XCJoZWFkZXJcIj48L3Nsb3Q+XG4gICAgPC9oZWFkZXI+XG4gICAgPG1haW4+XG4gICAgICA8c2xvdD48L3Nsb3Q+XG4gICAgPC9tYWluPlxuICAgIDxmb290ZXI+XG4gICAgICA8c2xvdCBuYW1lPVwiZm9vdGVyXCI+PC9zbG90PlxuICAgIDwvZm9vdGVyPlxuICA8L2Rpdj5cbjwvdGVtcGxhdGU+XG5cbjxzdHlsZT5cbiAgZm9vdGVyIHtcbiAgICBib3JkZXItdG9wOiAxcHggc29saWQgI2NjYztcbiAgICBjb2xvcjogIzY2NjtcbiAgICBmb250LXNpemU6IDAuOGVtO1xuICB9XG48L3N0eWxlPiJ9)
222
+
223
+
</div>
224
+
<divclass="options-api">
225
+
226
+
[Try it in the Playground](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdD5cbmltcG9ydCBCYXNlTGF5b3V0IGZyb20gJy4vQmFzZUxheW91dC52dWUnXG4gIFxuZXhwb3J0IGRlZmF1bHQge1xuICBjb21wb25lbnRzOiB7XG4gICAgQmFzZUxheW91dFxuICB9XG59XG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8QmFzZUxheW91dD5cbiAgICA8dGVtcGxhdGUgI2hlYWRlcj5cbiAgICAgIDxoMT5IZXJlIG1pZ2h0IGJlIGEgcGFnZSB0aXRsZTwvaDE+XG4gICAgPC90ZW1wbGF0ZT5cblxuICAgIDx0ZW1wbGF0ZSAjZGVmYXVsdD5cbiAgICAgIDxwPkEgcGFyYWdyYXBoIGZvciB0aGUgbWFpbiBjb250ZW50LjwvcD5cbiAgICAgIDxwPkFuZCBhbm90aGVyIG9uZS48L3A+XG4gICAgPC90ZW1wbGF0ZT5cblxuICAgIDx0ZW1wbGF0ZSAjZm9vdGVyPlxuICAgICAgPHA+SGVyZSdzIHNvbWUgY29udGFjdCBpbmZvPC9wPlxuICAgIDwvdGVtcGxhdGU+XG4gIDwvQmFzZUxheW91dD5cbjwvdGVtcGxhdGU+IiwiaW1wb3J0LW1hcC5qc29uIjoie1xuICBcImltcG9ydHNcIjoge1xuICAgIFwidnVlXCI6IFwiaHR0cHM6Ly9zZmMudnVlanMub3JnL3Z1ZS5ydW50aW1lLmVzbS1icm93c2VyLmpzXCJcbiAgfVxufSIsIkJhc2VMYXlvdXQudnVlIjoiPHRlbXBsYXRlPlxuICA8ZGl2IGNsYXNzPVwiY29udGFpbmVyXCI+XG4gICAgPGhlYWRlcj5cbiAgICAgIDxzbG90IG5hbWU9XCJoZWFkZXJcIj48L3Nsb3Q+XG4gICAgPC9oZWFkZXI+XG4gICAgPG1haW4+XG4gICAgICA8c2xvdD48L3Nsb3Q+XG4gICAgPC9tYWluPlxuICAgIDxmb290ZXI+XG4gICAgICA8c2xvdCBuYW1lPVwiZm9vdGVyXCI+PC9zbG90PlxuICAgIDwvZm9vdGVyPlxuICA8L2Rpdj5cbjwvdGVtcGxhdGU+XG5cbjxzdHlsZT5cbiAgZm9vdGVyIHtcbiAgICBib3JkZXItdG9wOiAxcHggc29saWQgI2NjYztcbiAgICBjb2xvcjogIzY2NjtcbiAgICBmb250LXNpemU6IDAuOGVtO1xuICB9XG48L3N0eWxlPiJ9)
227
+
228
+
</div>
229
+
225
230
Note that **`v-slot` can only be added to a `<template>`** (with [one exception](#abbreviated-syntax-for-lone-default-slots))
226
231
232
+
## Dynamic Slot Names
233
+
234
+
[Dynamic directive arguments](/guide/essentials/template-syntax.md#dynamic-arguments) also work on `v-slot`, allowing the definition of dynamic slot names:
235
+
236
+
```vue-html
237
+
<base-layout>
238
+
<template v-slot:[dynamicSlotName]>
239
+
...
240
+
</template>
241
+
242
+
<!-- with shorthand -->
243
+
<template #[dynamicSlotName]>
244
+
...
245
+
</template>
246
+
</base-layout>
247
+
```
248
+
249
+
Do note the expression is subject to the same [syntax constraints](/guide/essentials/template-syntax.html#directives) of dynamic directive arguments.
250
+
227
251
## Scoped Slots
228
252
229
-
Sometimes, it's useful for slot content to have access to data only available in the child component. It's a common case when a component is used to render an array of items, and we want to be able to customize the way each item is rendered.
253
+
As discussed in [Render Scope](#render-scope), slot content does not have access to state in the child component.
254
+
255
+
However, there are cases where it could be useful if the child component can selectively expose data to the slot content passed by the parent. For example, we can have a
256
+
257
+
- Think of scoped slots as callback functions being passed into the child component (in fact, slots are compiled into functions!)
258
+
- The child component call the slot function while passing it props
259
+
- The slot function use the props to render and return content
230
260
231
261
For example, we have a component, containing a list of todo-items.
232
262
@@ -378,56 +408,3 @@ You can even define fallbacks, to be used in case a slot prop is undefined:
378
408
<span class="green">{{ item }}</span>
379
409
</todo-list>
380
410
```
381
-
382
-
## Dynamic Slot Names
383
-
384
-
[Dynamic directive arguments](/guide/essentials/template-syntax.md#dynamic-arguments) also work on `v-slot`, allowing the definition of dynamic slot names:
385
-
386
-
```vue-html
387
-
<base-layout>
388
-
<template v-slot:[dynamicSlotName]>
389
-
...
390
-
</template>
391
-
</base-layout>
392
-
```
393
-
394
-
## Named Slots Shorthand
395
-
396
-
Similar to `v-on` and `v-bind`, `v-slot` also has a shorthand, replacing everything before the argument (`v-slot:`) with the special symbol `#`. For example, `v-slot:header` can be rewritten as `#header`:
397
-
398
-
```vue-html
399
-
<base-layout>
400
-
<template #header>
401
-
<h1>Here might be a page title</h1>
402
-
</template>
403
-
404
-
<template #default>
405
-
<p>A paragraph for the main content.</p>
406
-
<p>And another one.</p>
407
-
</template>
408
-
409
-
<template #footer>
410
-
<p>Here's some contact info</p>
411
-
</template>
412
-
</base-layout>
413
-
```
414
-
415
-
However, just as with other directives, the shorthand is only available when an argument is provided. That means the following syntax is invalid:
416
-
417
-
```vue-html
418
-
<!-- This will trigger a warning -->
419
-
420
-
<todo-list #="{ item }">
421
-
<i class="fas fa-check"></i>
422
-
<span class="green">{{ item }}</span>
423
-
</todo-list>
424
-
```
425
-
426
-
Instead, you must always specify the name of the slot if you wish to use the shorthand:
0 commit comments