vue slot details

Slot is a placeholder provided to the parent component in the child component. It is represented by < slot > < / slot >. The parent component can fill any template code in this placeholder, such as HTML, component, etc. the filled content will replace the < slot > < / slot > tag of the child component.
The purpose of the slot is to make the component more scalable. How to package a good component? To extract commonalities into different slots is to expose commonalities into different components. Once we reserve the slot, users can decide what to insert into the slot according to their own needs.

1, Basic use of slot

// Parent component test Vue content
    <test-child>
      {{data.user}}  // Replace the contents in < slot > < / slot >
    </test-child>

// Subcomponent testchild Vue content
    <template>
       <div>
          <slot></slot>  // The slot name defaults to default
          // < slot > you can also give a backup content < / slot >
       </div>
    </template>

Note: if the < test child > template does not contain a < slot > element, anything between the start tag and the end tag of the component will be discarded.

2, Named slot

v-slot has been updated since 2.6.0. The obsolete syntax of using slot attribute and slot scope attribute is shown in Section 4 below.

(1) Basic use

// Parent component test Vue content
    <test-child>
      <template v-slot:header>  // v-slot:header can be abbreviated as: #header
         I am header slot 
      </template>
      
      <div>One without name of <slot> The exit will have an implied name“ default". </div>
      <p>I belong to <slot></slot> Default slot content</p>
      
      <template v-slot:footer>
         I am footer slot 
      </template>
    </test-child>

// Subcomponent testchild Vue content
    <template>
       <header>
          <slot name="header"></slot>
       </header>
       
       <slot></slot>
          
       <footer>
          <slot name="footer"></slot>
       </footer>
    </template>

Note: V-slots can only be added to < template > (there is only one special case: see exclusive default slots below)

(2) Abbreviation syntax for exclusive default slots

The special case of v-slot is that when the content provided is only the default slot, the component label can be used as the template of the slot. In this way, we can use v-slot directly on components:

<test-child v-slot>
   There are only default slots in this subcomponent<slot><slot>Yes to use on this component v-slot
</test-child>

3, Scope slot

The fundamental purpose of the scope slot is to enable the contents of the slot in the parent component to access the data only in the child component

(1) Abbreviation syntax for default slot

// Subcomponent testchild Vue content
    <template>
       <div>
          <slot v-bind:user="user"> //Slot prop must be bound, otherwise the parent cannot access it
             {{ user.name }}
          </slot>
       </div>
    </template>


// In the parent component test Use in Vue
   // < test child V-slot: default = "scope" > the following is the abbreviation
   <test-child v-slot="scope"> // scope can be named arbitrarily
         {{ scope.user.name }}
   </test-child>

The attribute bound to the < slot > element is called slot prop. Now in the parent scope, we can use the v-slot with value to define the name of the slot prop we provide:

Add: in this example, we choose to name the object containing all slots prop as scope, but you can also use any name you like.

(2) Precautions for mixing default slot and named slot

Again, v-slot can only be added to < template >, unless it is the abbreviation syntax of the default slot

Examples of errors:

// This writing is invalid and will lead to warnings
<test-child v-slot="slotProps">
  {{ slotProps.user.name }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</test-child>

Correct writing: as long as multiple slots appear, always use the complete < template > based syntax for all slots:

<test-child>
  <template v-slot:default="slotProps">
    {{ slotProps.user.name }}
  </template>

  <template v-slot:other="otherSlotProps">
    ...
  </template>
</test-child>

Note: the abbreviation syntax of the default slot cannot be mixed with the named slot because it will lead to ambiguous scope:

(3) Deconstruct slot Prop

Internal working principle of scope slot: wrap the contents of your slot in a function with a single parameter:

function (slotProps) {
  // Slot content
}

This means that the value of v-slot can actually be any JavaScript expression that can be used as a parameter in the function definition. Therefore, in the supported environment (single file component or modern browser), you can also use ES2015 deconstruction to pass in the specific slot prop, as follows:

<test-child v-slot="{ user }">
  {{ user.name }}
</test-child>

This can make the template more concise, especially when multiple props are provided in the slot. It also enables other possibilities such as prop renaming, such as renaming user to person:

<test-child v-slot="{ user: person }">
  {{ person.name }}
</test-child>

You can even define backup content for cases where the slot prop is undefined:

// Contents of the sub component test child 
<template>
    <slot></slot>
</template>

// Parent component writing method (the backup data can be customized when the child component does not bind any attribute)
<test-child v-slot="{ user = { name: 'Guest' } }">
  {{ user.name }}
</test-child>

4, Dynamic slot name

Dynamic instruction parameters can also be used on v-slot to define dynamic slot names:

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>
</base-layout>

5, Obsolete named slot

The v-slot instruction has been introduced since Vue 2.6.0 to provide a better API alternative to support slot and slot scope attribute. In all the next 2 In the X version, slot and slot scope attributes will still be supported, but they have been officially discarded and will not appear in Vue 3.

(1) Named slot with slot attribute

Using a special slot attribute on < template >, you can pass the content from the parent to the named slot:

<base-layout>
  <template slot="header">
    <h1>Here might be a page title</h1>
  </template>

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

  <template slot="footer">
    <p>Here's some contact info</p>
  </template>
</base-layout>

Or use slot attribute directly on a common element:

<base-layout>
  <h1 slot="header">Here might be a page title</h1>

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

  <p slot="footer">Here's some contact info</p>
</base-layout>

Note: there is a big difference between the usage of v-slot and slot: slot can be used on a common element, while v-slot can only be used on the template (of course, there is a special case, see above)

(2) Scope slot with slot scope attribute

Use the special slot scope attribute on < template > to receive the prop passed to the slot

<slot-example>
  <template slot="default" slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

The slot scope here declares that the received prop object will exist in the < template > scope as a slotProps variable. You can name slotProps as you want to name JavaScript function parameters.

slot="default" here can be ignored as an implicit writing method:

<slot-example>
  <template slot-scope="slotProps">
    {{ slotProps.msg }}
  </template>
</slot-example>

Slot scope attribute can also be directly used for non < template > elements (including components):

<slot-example>
  <span slot-scope="slotProps">
    {{ slotProps.msg }}
  </span>
</slot-example>

The value of slot scope can receive any valid JavaScript expression that can appear at the position of the parameter defined by the function. This means that in supported environments (single file components or modern browsers), you can also use ES2015 deconstruction in expressions, as follows:

<slot-example>
  <span slot-scope="{ msg }">
    {{ msg }}
  </span>
</slot-example>

Using the < todo list > described here as an example, the equivalent code using slot scope is:

<todo-list v-bind:todos="todos">
  <template slot="todo" slot-scope="{ todo }">
    <span v-if="todo.isComplete">✓</span>
    {{ todo.text }}
  </template>
</todo-list>

Keywords: Front-end Vue

Added by kef on Fri, 04 Mar 2022 20:10:32 +0200