VDone Demo VDone Demo
Home
  • Articles

    • JavaScript
  • Study Notes

    • JavaScript Tutorial
    • Professional JavaScript
    • ES6 Tutorial
    • Vue
    • React
    • TypeScript: Build Axios from Scratch
    • Git
    • TypeScript
    • JS Design Patterns
  • HTML
  • CSS
  • Technical Docs
  • GitHub Tips
  • Node.js
  • Blog Setup
  • Learning
  • Interviews
  • Miscellaneous
  • Practical Tips
  • Friends
About
Bookmarks
  • Categories
  • Tags
  • Archives
GitHub (opens new window)

Nikolay Tuzov

Backend Developer
Home
  • Articles

    • JavaScript
  • Study Notes

    • JavaScript Tutorial
    • Professional JavaScript
    • ES6 Tutorial
    • Vue
    • React
    • TypeScript: Build Axios from Scratch
    • Git
    • TypeScript
    • JS Design Patterns
  • HTML
  • CSS
  • Technical Docs
  • GitHub Tips
  • Node.js
  • Blog Setup
  • Learning
  • Interviews
  • Miscellaneous
  • Practical Tips
  • Friends
About
Bookmarks
  • Categories
  • Tags
  • Archives
GitHub (opens new window)
  • 基础

  • 组件

    • Component Usage Details
    • Passing Data from Parent to Child Components
    • Child Component Emitting Events and Values to Parent
    • Prop Validation and Non-Prop Attributes
    • Custom Events
    • Sibling Component Communication
    • Non-Parent-Child Component Communication
    • Parent Calling Child Component Methods with Arguments
    • Slots
      • Slot Basics
        • Default Content
      • Named Slots
      • Scoped Slots
        • Purpose:
      • Named Slot Shorthand
      • Demo
    • Dynamic Components and v-once Directive
    • Vue Parent-Child Component Lifecycle Order
  • 过渡&动画

  • 可复用性&组合

  • 工具

  • 规模化

  • Vuex

  • 其他

  • 《Vue》笔记
  • 组件
xugaoyi
2020-02-16
Contents

Slots

# Slots

API (opens new window)

# Slot Basics

<div id="root">
    <child> <!-- component tag -->
        <h1>hello</h1>
    </child>
</div>

<script type="text/javascript">
    Vue.component('child', { // child component
        template: '<div><slot></slot></div>'
    })

    var vm = new Vue({
        el: '#root'
    })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

In the code above, the h1 inside the component tag is the element to be inserted into the child component. The child component uses the slot tag to receive the h1 tag passed from the parent.

# Default Content

Vue.component('child', {
    template: '<div><slot>Default content</slot></div>'
})
1
2
3

The child component's slot tag can contain default content, which is only rendered when the parent does not provide any content.

# Named Slots

Warning

Updated in 2.6.0. The slot attribute syntax has been deprecated.

<div id="root">
    <child>
        <div slot="header">header</div> <!--old syntax: can use template or other tags-->
        <div slot="footer">footer</div>
    </child>
</div>

<script type="text/javascript">
    Vue.component('child', {
        template: `<div>
                        <slot name="header"></slot>
                        <div>content</div>
                        <slot name="footer"></slot>
                    </div>`
    })

    var vm = new Vue({
        el: '#root'
    })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

In the code above, the component tag has two elements with different slot attribute values. The child component has two slot tags with corresponding name attributes to receive the content passed from the parent.

Tip

Since 2.6.0, use the v-slot directive instead of the slot attribute syntax.

<div id="root">
    <child>
        <template v-slot:header> <!--new syntax: can only use template tag-->
            <h1>Title</h1>
        </template>
        <p>Content</p>
        <template v-slot:footer>
            <p>Footer</p>
        </template>
    </child>
</div>
<script type="text/javascript">
	Vue.component('child', {
		template: `<div>
						<header>
						   <slot name="header"></slot>
						</header>
						<main>
						  <slot></slot>
						</main>
						<footer>
						  <slot name="footer"></slot>
						</footer>
					</div>`
	})

    var vm = new Vue({
        el: '#root'
    })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

Since version 2.6.0, named slots use the v-slot directive instead of the slot tag attribute, e.g. v-slot:header. Inside the child component, slot tags still use the name attribute to receive content. Unnamed slots receive content that does not use v-slot.

Additionally, named slots can also use default content.

Note that v-slot can only be added to <template> tags (with one exception (opens new window)), which is different from the deprecated slot attribute (opens new window).

# Scoped Slots

Warning

Updated in 2.6.0. The slot-scope attribute syntax has been deprecated.

<div id="root">
    <child>
        <template slot-scope="dataObj"> <!--can use other tags, but they will be included in the slot-->
            <li>{{dataObj.dataItem}}</li>
        </template>
    </child>
</div>
<script type="text/javascript">
	Vue.component('child', {
        data(){
            return {
                list: [1, 2, 3, 4]
            }
        },
        template: `<div>
						<ul>
							<slot
								v-for="item of list"
								:dataItem=item
							>
							</slot>
						</ul>
					  </div>`
    })

    var vm = new Vue({
        el: '#root'
    })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

In the code above, the component tag uses a template tag with the slot-scope attribute to receive values passed from the child component. The li tag inside template is the element inserted into the slot, and dataObj.dataItem data is provided by the child component. The child component uses v-for to loop and insert the li tags provided by the parent, while passing each item via :dataItem=item.

The child component provides the data, the parent component receives the data, processes it, inserts it into elements, and then places the elements into the child component's slot.

# Purpose:

Data is provided by the child component, but the parent decides which elements to render, and can perform secondary processing on the data.

Tip

Since 2.6.0, use v-slot instead of the slot-scope attribute syntax.

To make user available in the parent slot content, we can bind user as an attribute of the <slot> element:

<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>
1
2
3
4
5

Attributes bound to a <slot> element are called slot props. Now, in the parent scope, we can use v-slot with a value to define a name for the slot props we've been provided:

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>
1
2
3
4
5

In this example, we chose to name the object containing all slot props as slotProps, but you can use any name you like.

<div id="root">
    <child>
        <template v-slot:default="dataObj"> <!--default is the default name and can be omitted, but not when there are multiple slots-->
            <li>{{dataObj.dataItem}}</li>
        </template>
    </child>
</div>

<script type="text/javascript">
	Vue.component('child', {
        data(){
            return {
                list: [1, 2, 3, 4]
            }
        },
        template: `<div>
						<ul>
							<slot
								v-for="item of list"
								:dataItem=item
							>
							</slot>
						</ul>
					  </div>`
    })

    var vm = new Vue({
        el: '#root'
    })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# Named Slot Shorthand

Just like v-on and v-bind, v-slot also has a shorthand, replacing everything before the argument (v-slot:) with the character #. For example, v-slot:header can be rewritten as #header:

<base-layout>
  <template #header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template #footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>
1
2
3
4
5
6
7
8
9
10
11
12

However, just like other directives, the shorthand is only available when an argument is provided. This means the following syntax is invalid:

<!-- This will trigger a warning -->
<current-user #="{ user }">
  {{ user.firstName }}
</current-user>
1
2
3
4

If you wish to use the shorthand, you must always specify the slot name instead:

<current-user #default="{ user }">
  {{ user.firstName }}
</current-user>
1
2
3

# Demo

See the Pen 插槽slot by xugaoyi (@xugaoyi) on CodePen.

Edit (opens new window)
#Vue
Last Updated: 2026/03/21, 12:14:36
Parent Calling Child Component Methods with Arguments
Dynamic Components and v-once Directive

← Parent Calling Child Component Methods with Arguments Dynamic Components and v-once Directive→

Recent Updates
01
How I Discovered Disposable Email — A True Story
06-12
02
Animations in Grid Layout
09-15
03
Renaming a Git Branch
08-11
More Articles >
Theme by VDone | Copyright © 2026-2026 Nikolay Tuzov | MIT License | Telegram
  • Auto
  • Light Mode
  • Dark Mode
  • Reading Mode