Because in 2.6.0, a new uniform syntax (the V-slot directive) was introduced for named slots and scoped slots. It replaces slot and slot-scope, and now the Internet is talking about some old versions of the content, the official documentation is not easy to understand, so I put together an article about the use of slots


Slot, commonly known as “Slot”, occupies a Slot in a component template. When the component tag is used, the contents of the component tag are automatically filled in (replacing Slot positions in the component template) and can be used as an outlet for distribution content

The content of the slot

Define two components home.vue and test.vue and reference the test.vue component in the home.vue component

Slots can contain plain text

//home.vue
<test>
     Hello Word
</test>
Copy the code
//test.vue
<a href="#">
	 <slot></slot>
</a>
Copy the code

When the component is rendered,
is replaced with Hello Word

Slots can also contain any template code, including HTML

Add the Font Awesome icon to your index. HTML and use it directly Href = “/ / netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css” rel = “stylesheet” >

//home.vue
<test> <! -- Add a Font Awesome icon --> <span class="fa fa-user"></span>
    Hello Word
</test>
Copy the code

Add other components to the slot

//home.vue
<test> <! <font awesome-icon></font awesome-icon> Hello Word </test>
Copy the code

If

does not contain a

element, anything between the component’s start tag and end tag is discarded.

Use data in slots

Slots have access to the same instance properties (that is, the same “scope “) as the rest of the template, but not to the scope of

//home.vue
<testHello {{enhavo}} </test>

data() {return{
		enhavo:'word'}}Copy the code
//home. Vue // We can't get the name because the value is passed to <test> <test name='you'>
    Hello {{name}}
</test>
Copy the code

Rule: Everything in the parent template is compiled in the parent scope; Everything in a subtemplate is compiled in a subscope.

Backup content (default content) slot

Sometimes we need to give the slot a specific default content, when other components do not give you the content, the default content will be rendered

<slot>Submit</slot> </slot>Copy the code

Use test.vue directly in home.vue as follows:

//home.vue
<test></test>
Copy the code

The final default, Submit, will be rendered

<button>
   Submit
</button>
Copy the code

What if we provide content?

//home.vue
<test< / > buttontest>
Copy the code

The supplied content will be rendered instead of the default content

< button > button < / button >Copy the code

A named slot

Sometimes we need more than one slot in a component

So what to do? In such cases, the

element has a special feature: name, which can be used to define additional slots

<div> <header> <! -- We want to put the header here --> </header> <main> <! -- We want to put the main content here --> </main> <footer> <! </footer> </div>Copy the code

At this point, we can use the name attribute

<div>
  <header>
    <slot name="header"></slot>
  </header>
  
  <main>
    <slot></slot>
  </main>
  
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
Copy the code

If a

does not have a name attribute, its name defaults to default. When feeding content to a named slot, we can use the V-slot directive on the

<div>
   <template v-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 v-slot:footer>
    <p>Here some contact info</p>
  </template>
</div>
Copy the code

Now everything in the

If you want to be more specific, set name=”default” in the main content slot and wrap it around it

<template v-slot:default>
	<p>A paragraph for the main content.</p>
	<p>And another one.</p>
</template>
Copy the code

Note:v-slotCan only be added in one<template>(with one exception, it will be said below)

Scope slot

As mentioned above, slots have access to the same instance properties (that is, the same “scope “) as the rest of the template, but not to the scope of

So what if you want to access the

scope? We bind the content we want to pass to

, and then set a value in the parent component with V-slot to define the name of the slot we provide:

//test.vue <div> <! {{user.lastName}} get Jun --> <! -- If the slot is given a value in home.vue, Jun is not displayed --> <! -- set a usertext and bind user to the set usertext --> <slot v-bind:usertext="user">{{user.lastname}}</slot> </div> // define contentdata() {return{
	user:{
	  firstName:"Fan",
	  lastName:"Jun"}}}Copy the code

Then it receives the value passed to it in home.vue:

//home.vue
<div>
  <test v-slot:default="slotProps">
    {{slotProps.usertext.firstName}}
  </test>
</div>
Copy the code

This will get the value passed by the test.vue component

Features bound to

elements are called slot prop. In the parent component, we can set a value with v-slot to define the name of the slot prop we provide, and then use it directly

Exclusive default slot abbreviation syntax

In this case, the component’s label can be used as a template for the slot only if the content provided is the default slot. This allows us to use V-slot directly on components

This can also be simpler because v-slot without arguments is assumed to be the default slot, so the code above can be simplified:

<div> <! -- You can drop :default, only the default slot --> <test v-slot="slotProps">
    {{slotProps.usertext.firstName}}
  </test>
</div>
Copy the code

Note: The default slot abbreviation syntax cannot be mixed with named slots, as it would result in undefined scope

<div> <! -- You can drop :default, only the default slot --> <test v-slot="slotProps"> {{slotProps.usertext.firstName}} <! -- invalid, warning --> <template V-slot :other="otherSlotProps">
      slotProps is NOT available here
    </template>
  </test>
</div>
Copy the code

Whenever multiple slots are present, always use full

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

  <template v-slot:other="otherSlotProps">... </template> </test>
Copy the code

Deconstructing slot Prop

Because the inner workings of a scope slot are to include the contents of your slot in a function that passes in a single argument, this means that the value of the V-slot can actually be any JS expression that can be used as an argument in the function definition

So this is what it originally said:

<div>
  <test v-slot="slotProps">
    {{slotProps.usertext.firstName}}
  </test>
</div>
Copy the code

You can also write:

<div>
  <test v-slot={usertext}>
    {{usertext.firstName}}
  </test>
</div>
Copy the code

This can make the template more concise, especially if the slot provides multiple prop. It also opens up other possibilities like prop renaming,

For example, you could rename usertext to person:

<div>
  <test v-slot={usertext:person}>
    {{person.firstName}}
  </test>
</div>
Copy the code

You can even define backup content (default content) for situations where the default content can be used when the slot has no value:

<div>
  <test v-slot="{usertext={firstName:'Yang'}}">
    {{usertext.firstName}}
  </test>
</div>
Copy the code

Dynamic Slot Name (Added in 2.6.0)

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

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

Abbreviations for named Slots (added in 2.6.0)

Like v-on and v-bind, v-slot has an abbreviation that replaces everything before the argument (v-slot:) with the character #. For example, v-slot:header can be rewritten as #header:

This is what it said:

<div>
   <template v-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 v-slot:footer>
    <p>Here some contact info</p>
  </template>
</div>  
Copy the code

Now you can write:

<div>
   <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 some contact info</p>
  </template>
</div>
Copy the code

Note: This directive, like other directives, is only available if it has arguments

The following is incorrect:

<test #="{ usertext }">
  {{ usertext.firstName }}
</test>
Copy the code

If you want to use abbreviations, you must always use an explicit slot name instead:

<test #default="{ usertext }">
  {{ usertext.firstName }}
</test>
Copy the code

Other examples

Slot Prop allows us to convert slots into reusable templates that can render different content based on the input prop. This is most useful when designing reusable components that encapsulate data logic while allowing the parent component to customize the partial layout.

For example, we want to implement a

component that is a list and contains layout and filtering logic:

<ul>
  <li
    v-for="todo in filteredTodos"
    v-bind:key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>
Copy the code

We can use each todo as a slot for the parent component to control it through the parent component, and then bind toDO as a slot prop:

<ul>
  <li
    v-for="todo in filteredTodos"
    v-bind:key="todo.id"> <! We prepare a slot for each todo, passing the 'todo' object as a prop for the slot. --> <slot name="todo" v-bind:todo="todo"> <! {{todo.text}} </slot> </li> </ul>Copy the code

Now when we use the

component, we can choose to define a different

<todo-list v-bind:todos="todos">
  <template v-slot:todo="{ todo }">
    <span v-if="todo.isComplete"> ✓ < / span > {{todo. Text}} < / template > < / todo list - >Copy the code

As for the ones that are abandonedslotslot-scopeFeatures are not described here. If you are interested, please refer to the official documentation

Bye bye

@ _ @