Detailed explanation of usage and scope of slots in vue slots

foreword

Slots are a very useful tool in Vue. This article will explain the basic usage of vue slots and explain scoped slots in detail.

Hope to be helpful to readers!

1. Basic use of slots

1.1 Leading out the slot

When we reuse components, although the data of the components can be changed by passing values ​​from parent to child, the structure of the page still depends on the components themselves.

So, how can you add what you want on the basis of the structure of the component itself without changing the structure of the component itself? It can be done using slots.

Slot concept:
A slot is a placeholder in a child component that is provided to the parent component. It is represented by a slot tag. The parent component can fill any template code in this placeholder, such as HTML, components, etc., and the filled content Will replace the slot label of the child component. A simple understanding is that there is a "pit" left in the child component, and the parent component can use the specified content to fill the "pit".

1.2 Basic use of slots

As shown below, a parent component reuses child components:

<template>
  <div class="container">
    <Student></Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

The structure of student is also very simple:

<template>
  <div class="student">
      <h3>巧克力小猫猿</h3></div>
</template>

The final effect:
insert image description here

Now, without changing the student component, I want to add a 'gas' to the top of 'Chocolate Kitty Ape', so we can use slots.

Slots are actually very simple, and the combination definition is not difficult to understand. we can inSubassemblyDig a pit for the parent component, and the parent component puts the content into the pit of the child component:

Digging pits with slot labels in subcomponents

<template>
  <div class="student">
    <slot></slot>
    <h3>巧克力小猫猿</h3>
  </div>
</template>

Fill in the hole in the parent component:

<template>
  <div class="container">
    <Student>加油</Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

So you can see the effect:
insert image description here
also if we want to add a fuel to the bottom of the 'Chocolate Kitty Ape', we can dig a hole under this structure:

<template>
  <div class="student">
    <!-- <slot></slot> -->
    <h3>巧克力小猫猿</h3>
    <slot></slot>
  </div>
</template>

So the effect becomes:
insert image description here
the above is the basic use of the slot.

1.3 Default slots

When we use slots, we can see that a slot hole is dug for the child component, and the content of the hole is filled in the label of the child component name in the parent component.

What if the content is not specified in the parent component and we need a default value?

It's very simple, just set a default value for the slot:

<template>
  <div class="student">
    <!-- <slot></slot> -->
    <h3>巧克力小猫猿</h3>
    <slot>我是默认值</slot>
  </div>
</template>

In the parent component, only the first student instance object specifies the content of the slot, and the others do not:

<template>
  <div class="container">
    <Student>加油</Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

Then the display content of the specified content, and the default content of the unspecified content:
insert image description here
this is the default slot.

1.4 Slot Style

The parent component fills the hole, and the style can be written in the style of the parent component:

<template>
  <div class="container">
    <Student>
      <h3 class="up">加油</h3>
    </Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

style:

.up {
    
    
  color: skyblue
}

Effect:
insert image description here
Why can it be written like this: the slot and its internal content can be parsed by vue.

The above is the basic use of the slot.

Second, the named slot

2.1 Leading out named slots

It's still the original structure, nothing:
insert image description here
but the demand has increased, I want to write 'Come on' above 'Chocolate Kitty Ape', and 'Find a job' below. So, how to do it?

If it can be achieved according to the method just now, but only the default slot can be used. This is not possible once the parent component provides content to fill the slot:

<template>
  <div class="student">
    <slot>加油</slot>
    <h3>巧克力小猫猿</h3>
    <slot>找到工作</slot>
  </div>
</template>

insert image description here
But the current requirement is not to use the default slot, but to provide content implementation through the parent component, how to do it? Named slots do the trick for us.

2.2 Use of named slots

A named slot, known by its name, is a slot with a name.

To solve the problem just now, we only need to put the same mark on the slot and the corresponding content module. Let vue know what content to fill into which slot.

In the child component, give the slot a name:

<template>
  <div class="student">
    <slot name="up"></slot>
    <h3>巧克力小猫猿</h3>
    <slot name="job"></slot>
  </div>
</template>

In the parent component, specify the slot name that needs to be placed for the content:

<template>
  <div class="container">
    <Student>
      <h3 slot="up">加油</h3>
      <h3 slot="job">找到工作</h3>
    </Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

Therefore, with such a one-to-one correspondence, the content can be successfully filled:
insert image description here
this is the named slot.

Three, template tag

3.1 Lead out template tag

Still the original structure:
insert image description here
current demand: use named tags, add an h3 tag and a div tag below the 'Chocolate Kitty Ape'.

I believe that after understanding the above explanation, this problem should be solved easily:
in the parent component:

<template>
  <div class="student">
    <h3>巧克力小猫猿</h3>
    <slot name="add"></slot>
  </div>
</template>

In the subcomponent:

<template>
  <div class="container">
    <Student>
      <h3 slot="add">加油</h3>
      <div slot="add">找到工作</div>
    </Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

Effect:
insert image description here
The effect is realized. But if it would be troublesome to write a slot for each added content, how to solve it?

We can set up a div and put all the content in it, so that we can only write one slot:

<template>
  <div class="container">
    <Student>
      <div slot="add">
        <h3>加油</h3>
        <div>找到工作</div>
      </div>
    </Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

The effect is exactly the same, but not good enough: because there is an extra div structure here:
insert image description here
so how to solve it, you can use the template tag.

3.2 Use of template tags

Very simple, just replace the outer div with the template tag:

<template>
  <div class="container">
    <Student>
      <template slot="add">
        <h3>加油</h3>
        <div>找到工作</div>
      </template>
    </Student>
    <Student></Student>
    <Student></Student>
  </div>
</template>

The effect is the same as before, but in terms of structure, there is no extra structure,Does not generate real DOM
insert image description here

Fourth, the scope slot

4.1 Exporting scoped slots

Please take a look at the following effects:
insert image description here
If you want to achieve this effect, what are the methods? There are many ways, which can be divided into two cases: Case 1, the data is in the sub-component, write the relevant content in the sub-component, and reuse it directly in the parent component; case 2, the data is in the parent component, by The parent component uses props to pass to the child component, and the child component can use data and traverse it.

But now there is a new requirement:data in child component, to use ul, ol two lists to display these data, how to do?

Let's analyze it, you can set the type in the parent component:

<template>
  <div class="container">
    <Student type="ul"></Student>
    <Student type="ol"></Student>
    <Student type="ul"></Student>
  </div>
</template>

Pass it to the sub-component, the sub-component is judged by v-show or v-if, if it is ul, it will be written in ul structure, if it is ol, it will be written in ol structure.

This accomplishes the goal, but is very cumbersome. How can this be achieved using an easier method?

Similarly, the simpler approach also comes from slots:

<template>
  <div class="container">
    <Student>
      <ul>
        <li v-for="stu in stus" :key="stu.index">{
    
    {
    
     stu }}</li>
      </ul> 
    </Student>
    <Student>
      <ol>
        <li v-for="stu in stus" :key="stu.index">{
    
    {
    
     stu }}</li>
      </ol>
    </Student>
    <student>
      <ul>
        <li v-for="stu in stus" :key="stu.index">{
    
    {
    
     stu }}</li>
      </ul> 
    </Student>
  </div>
</template>

In doing so, you can achieve content, use the same data, do different things.

However, don't forget that our initial condition is that the data is in the child component. So we also need to pass the data in the child component to the parent component in advance, which is also a bit troublesome.

Is there a better way? Take advantage of scoped slots.

4.2 Scoped slots

Here we can summarize what the scope slot is. As in the case just now, we use the slot to implement the problem in the parent component, but the slot is in the child component.

The data can only be used in subcomponents, because the scope of data is limited to subcomponents.

How to simply and conveniently pass the data in the child component to the structure to fill the slot in the parent component? Scoped slots can be implemented.

Please look at the subcomponent structure. In the slot label, similar to the use of v-bind, we pass the stus array to the parent component under the name of student:

<template>
  <div class="student">
    <slot :student="stus"></slot>
  </div>
</template>

<script>
export default {
    
    
    name: 'Student',
    data() {
    
    
        return {
    
    
            stus: ['巧克力', '小猫', '猿']
        }
    }
}
</script>

use in parent componenttemplateThe tag can be successfully received, and all the received data is placed in the scope and named data:

    <Student>
      <template scope="data">
      </template>
    </Student>

How to prove: we print the data of scope:

<template>
  <div class="container">
    <Student>
      <template scope="data">
        {
    
    {
    
     data }}
      </template>
    </Student>
  </div>
</template>

The result is:
insert image description here
It can be seen that data is an object, and all the passed data is stored inside. If we want to use student, data.student can be:

    <Student>
      <template scope="data">
        <ul>
          <li v-for="s in data.student" :key="s.index">{
    
    {
    
     s }}</li>
        </ul>
      </template>
    </Student>
  </div>

Effect:
insert image description here
So, we can easily realize the requirements:
insert image description here
this is how to use scoped slots.

We further understand the use of scope slots: when the data is in the component itself, but the structure generated according to the data needs to be determined by the component user, we can use scope slots.

postscript

The above is the relevant explanation of the slot, I hope to help readers and friends.

Welcome to pay attention, hope to bring you more exciting content!

Guess you like

Origin blog.csdn.net/zxdznyy/article/details/128819330