slots in vue3

what is a slot

Slots are a mechanism used in components to carry content, allowing components to accept arbitrary content from other components at runtime. It can be understood as a placeholder defined in the Vue component to specify the location of the content passed to the child component in the parent component. It can dynamically insert different content in the parent component as needed, and it can also accept the data passed down from the child component.
Create slots
In vue components, use <slot>tags to define slots. We first create a Product.vue component in the components folder, and <slot>use slots in the Product component. The code is as follows

<template>
  <div>
    <h2>这是插槽之前的内容</h2>
      <slot></slot>
    <h3>这是插槽之后的内容</h3>
  </div>
</template>
<script setup>
</script>
<style scoped>
</style>

Then introduce the component Product.vue in APP.vue, and <Product></Product>use a div in the middle of the label to fill in the content to be displayed in the slot of Product.vue

<template>
  <div>
    <Product>
      <div>这里是从APP.vue填入Product组件slot中的内容</div>
    </Product>
  </div>
</template>
<script setup>
import Product from './components/Product.vue'
</script>

<style scoped>
</style>

Run, refresh the browser, the effect is as follows
insert image description here

type of socket

There are three types of slots provided in Vue: default slots, named slots, and scoped slots.

default slot

The default slot is the simplest and most common kind of slot. It allows a component to receive any unnamed content and insert it as a child of the component. The default slot is usually declared by adding a slottag . For example, if we define a MyComponent.vue component, its code is as follows:

<template>
  <div>
    <slot></slot>
  </div>
</template>

When we render the component in App.vue, any content can be inserted into the component through this default slot, as follows:

<MyComponent>
  <h1>hello world</h1>
</MyComponent>

Here, when we call MyComponentthe component , MyComponentwe add a h1tag inside the tag and fill in a piece of content. This content will be injected into <slot></slot>the tag .

named slot

As the name implies, a named slot is a slot with a name, which allows developers to selectively insert content into a named slot of a component. Declaring a named slot is very simple, we only need to add a special attribute in the slot tag: name, which is used to assign a unique ID to each slot to determine the content to be rendered in each place. Named slots are declared like this:

<template>
  <div>
    <slot name="header"></slot>
    <slot></slot>
  </div>
</template>

In the code above, I declare two slots: a slot named "header", and a default slot. Named slots can be used like this: When
used in a parent component , to pass in content for a named slot, we need to use an element with a v-slot directive and pass the name of the target slot to the directive: v -slot can be abbreviated as #, so can abbreviated as . It means "pass this part of the template fragment into the header slot of the child component"<MyComponent><template><template v-slot:header>
<template v-slot:header><template #header>

<MyComponent>
  <template #header>
    <h1>custom header</h1>
  </template>
  <p>main content</p>
</MyComponent>

Scoped slots

Scope slots can be understood as "slots with data". In some scenarios, the content of the slot may want to use the data in the domain of the parent component and the domain of the child component at the same time. In this case, you need to use the scope slot. Scoped slots can be declared like this:

<template>
  <div>
    <slot name="header" :text="headerText"></slot>
  </div>
</template>

In the code above, a named slot is declared in MyComponentthe component #headerand passed a property textcalled .

We need to use the v-slot directive in the parent component to pass data into the scoped slot, like so:

<template>
  <MyComponent>
    <template #header="slotProps">
      <h1>{
    
    {
    
    slotProps.text}}</h1>
    </template>
  </MyComponent>
</template>

In the parent component, v-slotwe passed the data #headerto the slot using the directive.

The default content of the slot

It is possible to specify a default content for a slot in case nothing is provided externally. For example, there is such a SubmitButton component:

<button type="submit">
  <slot></slot>
</button>

If we want to render "submit" <button> inside , we just need to write "submit" <slot>between the tags as the default content:

<button type="submit">
  <slot>
    提交 <!-- 默认内容 -->
  </slot>
</button>

At this point, when we use it in the parent component without providing any slot content:

<SubmitButton />

"Submit" will be rendered as the default content:
but if we provide slot content:
save in the parent component
then the explicitly provided content will replace the default content

Using slots in dynamic components

In a dynamic component, the parent component where the slot is located needs to be wrapped with a component tag to specify the component that needs to change dynamically, and at the same time use the v-bind command to dynamically bind the parameters required by the component to a JS object and pass it to the dynamic component.

<template>
  <div>
    <component :is="currentComponent" v-bind="data">
      <slot v-bind:name="slotName"></slot>
    </component>
  </div>
</template>

Combination of slots

In a component, multiple slots can be used at the same time, and we can use <template>tags to combine multiple slots. At the same time, we can use <template>tags containing v-if and v-for instructions for more complex slot design.

<template>
  <div>
    <template #header>
      <h1>这是header插槽的内容</h1>
    </template>
    <template #main>
      <h1 v-if="showMainTitle">这是main插槽的标题</h1>
      <p v-for="item in list" :key="item.id">{
    
    {
    
     item.name }}</p>
    </template>
    <template #footer>
      <button @click="onClickFooterBtn">点击这个按钮会触发footer插槽的事件</button>
    </template>
  </div>
</template>

Advanced usage of slots

slot reuse

In actual development, the same slot may be reused in multiple components. At this time, the slot can be defined in an independent component and then referenced when needed. The following code demonstrates how to define a slot in an independent component, and then reference it in App.vue, ParentComponent.vue, and AnotherComponent.vue respectively, through the following steps:

1. First define a SlotComponent.vue component

<template>
  <div>
    <slot></slot>
  </div>
</template>

2. Then introduce and call the slot in a parent component ParentComponent.vue that needs to call the slot

<template>
  <div>
    <slot-component>
      <h4>这里是在ParentComponent组件中引入SlotComponent.vue插槽的内容</h4>
    </slot-component> 
  </div>
</template>
<script setup>
import SlotComponent from './SlotComponent.vue';
</script>
<style scoped>
</style>

3. Introduce and call the slot in AnotherComponent.vue, another parent component that needs to call the slot

<template>
  <div>
    <slot-component>
      <h4>这里是在AnotherComponent组件中引入SlotComponent.vue插槽的内容</h4>
    </slot-component> 
  </div>
</template>
<script setup>
import SlotComponent from './SlotComponent.vue';
</script>
<style scoped>
</style>

4. Introduce the above ParentComponent.vue, AnotherComponent.vue and SlotComponent.vue components in App.vue, the code is as follows

<template>
  <div>
    <AnotherComponent></AnotherComponent>
    <h6>---------------------------------</h6>
    <ParentComponent></ParentComponent>
    <h6>---------------------------------</h6>
    <div>
      <SlotComponent>
        <h4>这里是在App组件中引入SlotComponent.vue插槽的内容</h4>
      </SlotComponent>
    </div>    
  </div>
</template>
<script setup>
import AnotherComponent from './components/AnotherComponent.vue';
import ParentComponent from './components/ParentComponent.vue'; 
import SlotComponent from './components/SlotComponent.vue';
</script>
<style scoped>
</style>

Run the program, refresh the browser, you can see the effect as follows
insert image description here

Use dynamic components as slots

In actual development, we can also render dynamic components as the contents of slots. The sample code is as follows:

Define a component DynamicComponent.vue that needs to be displayed dynamically,

<template>
  <h4>我是动态组件,我也可以放入SlotComponent组件定义的插槽中</h4>
</template>
<script setup>
</script>
<style scoped>
</style>

In App.vue, pass the dynamic component to the SlotComponent.vue defined above for rendering.

 <SlotComponent>
      <template #default>
        <component v-bind:is="DynamicComponent"></component>
      </template>
</SlotComponent> 

Run, refresh the browser, you can see that the content has been rendered successfully
insert image description here

Priority rules for slots

1. The default slot content is specified in the parent component, and the slot name is not specified in the child component, and the parent component is inserted into the default slot by default.
parent component code

<SlotComponent>
      在子组件中没有指定插槽名,父组件默认插入到默认插槽中。
 </SlotComponent>

The code in the subcomponent SlotComponent

<template>
   <div>
    <slot></slot>
    <h4>***********************************</h4>
    <slot name="header">
      这里是名称为header插槽的默认内容
    </slot>
  </div>
</template>
<script setup>
</script>
<style scoped>
</style>

The operation effect is as follows
insert image description here
2. If a slot name is specified in the parent component, and there is a slot with the same name in the child component, the slot content of the parent component will overwrite the slot content of the child component.

The following code specifies the slot content named "header" in the parent component, and there is a slot with the same name in the child component, and the slot content of the parent component will override the slot content of the child component.

parent component code

 <SlotComponent>
      如果在父组件中指定了插槽名,在子组件中有相同名称的插槽,父组件插槽内容会覆盖子组件插槽内容。
      <template v-slot:header>
        父组件指定了名称为“header”的插槽内容,在子组件中有相同名称的插槽,父组件插槽内容会覆盖子组件插槽内容。
      </template>
    </SlotComponent>

Running effect
insert image description here
3. The v-slot instruction is used in the parent component, and no name is specified in the child component. The unnamed slot of the parent component will be assigned to the default slot of the child component.

<SlotComponent>   
  <template v-slot>
   在父组件中使用了 v-slot 指令,子组件中没有指定名称,父组件的未命名插槽会分配到子组件的名为“default”的插槽中。
  </template> 
 <template v-slot:header>
    这里是header插槽的内容
  </template>
</SlotComponent>

Run the code, the effect is as follows
insert image description here
4. The name is specified in both the parent component and the child component, and the slot content with the specified name in the parent component will overwrite the slot content with the same name in the child component.

Ok, this is the end of the introduction about how to use slots in vue3, friends who like it, like, follow and add to favorites!

Guess you like

Origin blog.csdn.net/w137160164/article/details/131134774