vue3 - the use of Slots

Although the title is the use of vue3 slots, in fact, vue2 is also used in the same way. There is no difference, but the writing method of vue3 is used in the case, which will be a little different;

1. Slot usage scenarios

We know that a child component can receive any type of js variable from the parent component for propsuse, so if the parent component wants to pass it to the child component HTML tags, template fragments, or even a component, how should the child component receive it?

Therefore, the emergence of slots can solve the above problems; 插槽slotsit can be subdivided into: default content, named slots, and scoped slots;

Here is the diagram :

insert image description here

In fact, it is to insert the content into the reserved position specified by the subcomponent. This position is<slot>

2, default content slot

Default content can be specified for slots in cases where the parent element does not provide any content. For example, there is such a SlotButtoncomponent;

Subcomponent SlotButton.vue:

<script setup>
import {
    
     reactive, ref, createApp } from "vue";
</script>

<template>
  <button class="btn primary">
    <!-- 插槽出口 -->
    <slot>默认内容</slot>
  </button>  <br>
</template>

Use the slot in the parent component:

<!-- 只传文本 -->
 <SlotButton> 我是插槽按钮 </SlotButton><br />

The final rendered button is as follows:

insert image description here

If the parent component does not pass anything, then by default the one in the child component's slot is used 默认内容:

 <SlotButton> </SlotButton><br />

as follows:

insert image description here

That is to say, the content passed in by the parent component will be inserted into <slot><slot>the position of the child component for rendering. css样式Try to write it in the parent component, and the child component can only display the content;

So now we only insert text content, then html tags and components can also be inserted into the slot. The following case will be mentioned;

3. Named slots

Sometimes a component contains multiple slots at the same time, for example header头部,body内容区,footer底部区, then we can use named slots to distinguish these slots in each position, that is to say, give each slot a name for specification.

See the example below:

insert image description here
Click the button to display the modal box, and the content in the modal box is divided into header slots, content area slots, and bottom slots;

Parent component code:

<script setup>
import {
    
     reactive, ref, createApp } from "vue";
import SlotButton from "@/components/component/SlotButton.vue";
import Modal from "@/components/component/Modal.vue";//引入组件
let isShowModal = ref(false);//控制是否显示模态框
const showModal = () => {
    
    
  isShowModal.value = true;
};
const closeModal = () => {
    
    
  isShowModal.value = false;//点击OK关闭模态框
};
</script>
<template>
  <div class="slot">
  	主要内容:
    <Modal @close="closeModal" :show="isShowModal">
      <template #header><p class="title">我是标题</p> </template>
      <template v-slot:body><p class="body">我是内容</p></template>
      <template v-slot:footer><p class="footer">我是底部内容</p></template>
    </Modal>
  </div>
</template>
<style scoped lang="less">
.title {
    
    
  text-align: center;
  color: blue;
}
</style>

It can be seen that when a named slot defines a slot entry, we need to use an element containing a v-slotdirective <template>, and pass the name of the target slot to the directive:

v-slotThere is a corresponding abbreviation #, so <template v-slot:header>can be abbreviated as <template #header>. It means "pass this part of the template fragment into the header slot of the child component".

Next, let's see how the subcomponent is written:

子组件Modal.vue:
Only the slot outlet part is shown here, there are too many css styles and will not be displayed

<template>
  <Transition name="modal">
    <div v-if="show" class="modal-mask">
      <div class="modal-container">
        <!-- 头部插槽的位置 -->
        <div class="modal-header">
          <slot name="header">default header</slot>
        </div>
        <!-- 内容区插槽的位置 -->
        <div class="modal-body">
          <slot name="body">default body</slot>
        </div>
        <!-- 底部插槽的位置 -->
        <div class="modal-footer">
          <slot name="footer"> </slot>
        </div>
        <!-- 关闭按钮 -->
        <button class="modal-default-button" @click="onClick">OK</button>
      </div>
    </div>
  </Transition>
</template>

Such nameslots with attributes are called named slot exits , and exits that are not provided nameare <slot>implicitly named "default". One-to-one correspondence with the #header passed in by the parent component, each responsible for rendering;

So far, the introduction of named slots is complete, and it can be seen that not only text, but also labels and components can be passed in slots;

4. Dynamic slot name

Dynamic directive parametersv-slot are also valid on , i.e. you can define dynamic slot names like this :

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

  <!-- 缩写为 -->
  <template #[dynamicSlotName]>
    ...
  </template>
</base-layout>

5. Scope slots

We know that the content of the slot cannot access the state of the child component, that is to say, the parent component cannot get the value in the slot outlet of the child component;

However in some scenarios the content of the slot may want to use data from both the parent component's scope and the child component's scope. To do this, we need a way for the child component to provide a portion of the data to the slot (the parent component) when it renders.

Subcomponent: SlotButton.vue

<template>
  <button class="btn primary">
    <!-- 插槽出口 -->
    <slot text="子组件内容" count="1">默认内容</slot>
  </button>  <br>
</template>

It can be seen that we defined two custom attributes on the slot, just want to pass these values ​​to the slot entry of the parent component;

parent component:

  <!--5, 作用域插槽 -->
    <div>
      <SlotButton v-slot="slotProps">  {
    
    {
    
     slotProps.text }} - {
    
    {
    
     slotProps.count }} </SlotButton>
    </div>

You can get an object in the parent component, and name it randomly (I am slotProps here), so that you can get the value in the slot; the rendering is as follows:
insert image description here

Of course, the objects here can also use destructuring syntax:

	<!--5,作用域插槽 使用对象的解构 -->
    <div>
      <SlotButton v-slot="{text,count}">  {
    
    {
    
     text }} - {
    
    {
    
     count }} </SlotButton>
    </div>

6. Named scoped slots

Named scope slots work similarly, slot props can v-slotbe accessed as the value of the directive: v-slot:name="slotProps". when using the abbreviation is<template #name="headerProps"></template>

parent component:

	<div>
      <SlotButton>
        <template #btn="btnProps">
          {
    
    {
    
    btnProps.text}} - {
    
    {
    
    btnProps.count}}
        </template>
      </SlotButton>
    </div>

Since it is a named slot, it must have nameattributes, so it is written <template #btn="btnProps"> btnas the name of the slot exit, as follows:

Subcomponent SlotButton.vue:

 <button class="primary">
    <!-- 插槽出口 -->
    <slot name="btn" text="子组件内容" count="1">默认内容</slot>
  </button>  <br>

Guess you like

Origin blog.csdn.net/qq_43886365/article/details/131822173