[Vue Family Bucket] Detailed slot

[Vue Family Bucket] Detailed slot

foreword

We've seen that components can receive any type of JavaScript value as props, but how do components receive template content? In some scenarios, we may want to pass some template fragments to the child components and let the child components render these fragments in their components.

1. Understanding Slot

In development, we often encapsulate reusable components one by one :

  • We will pass some data to the component through props, and let the component display it;
  • But in order to make this component more versatile, we cannot limit the content in the component to fixed div, span, etc. elements;
  • For example, in some cases we use a component and hope that the component displays a button, and in some cases we use a component and hope to display a picture;
  • We should allow users to decide what content and elements are stored in a certain area;

1.1 Basic use of slots

At this time, we can define the slot : 、

  • The process of using the slot is actuallyExtract commonality and reserve differences
  • we willCommon elements and content are still encapsulated in components
  • At the same time willDifferent elements use slots as placeholders, let the outside decide what kind of elements to display;

For example, here's a <FancyButton>component that can be used like this:

<FancyButton>
  Click me! <!-- 插槽内容 -->
</FancyButton>

<FancyButton>And the template for is this:

<button class="fancy-btn">
  <slot></slot> <!-- 插槽出口 -->
</button>

<slot>The element is a slot outlet , indicating where the slot content provided by the parent element will be rendered.

insert image description here

The final rendered DOM looks like this:

<button class="fancy-btn">Click me!</button>

<FancyButton>Components are more flexible and reusable by using sockets . Now components can be used in different places to render different content, but at the same time ensure that they all have the same style.

2. Use of slots

2.1 Default content

Sometimes we hope that when using a slot, if there is no corresponding content inserted, then we need to display adefault content

  • Of course, this default content will only be displayed when no inserted content is provided;

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

<template>
  <div>
    <h2>content 开始</h2>
    <slot></slot>
    <h2>content 结尾</h2>
  </div>
</template>

If we want to render the default content when the parent component does not provide any slot content , we only need to write the default content between the tags as the default content:<slot>

<template>
  <div>
    <h2>slot 开始</h2>
    <slot>
      <h2>默认显示的内容</h2>
    </slot>
    <h2>slot 结尾</h2>
  </div>
</template>

Now, when we use in a parent <ShowMessage>component without providing any slot content:

<ShowMessage />

will render the default content:

insert image description here

But if we provide the slot content:

<show-message>
    <button>登录</button>
</show-message>

Then the explicitly provided content will override the default content:

insert image description here

2.2 Title slot

When a component contains multiple slots and we insert multiple content

  • You will find that by default, each slot will get the content we inserted to display
<template>
  <div class="nav-bar">
    <div class="left">
      <slot></slot>
    </div>
    <div class="center">
      <slot></slot>
    </div>
    <div class="right">
      <slot></slot>
    </div>
  </div>
</template>
<template>
  <div>
    <nav-bar>
      <button>左边元素</button>
      <h2>中间标题</h2>
      <button>右边元素</button>
    </nav-bar>
  </div>
</template>

insert image description here

For this kind of scenario, <slot>the element can have a special attribute name, which is used to assign a unique ID to each slot to determine the content to be rendered in each place:

<div class="nav-bar">
    <div class="left">
        <slot name="left"></slot>
    </div>
    <div class="center">
        <slot name="center"></slot>
    </div>
    <div class="right">
        <slot name="right"></slot>
    </div>
</div>

nameSuch slots are called named slots. Exports that are not nameprovided <slot>are implicitly named "default".

When used in a parent component, we need a way to pass the contents of multiple slots into the outlets of their respective target slots. At this point you need to use named slots :

To pass in content for a named slot, we need to use v-slotan <template>element with a directive and pass it the name of the target slot:

<nav-bar>
    <template v-slot:left>
		<button>左边元素</button>
    </template>
    <template v-slot:center>
		<h2>中间标题</h2>
    </template>
    <template v-slot:right>
		<button>右边元素</button>
    </template>
</nav-bar>

insert image description here

Supplement :

  • We can dynamically bind a name through v-slot:[dynamicSlotName];
  • v-slotAbbreviation: (v-slot:) is replaced by the character #;

2.3 Scoped slots

In Vue there is the concept of render scope :

  • Everything in the parent template is compiled in the parent scope;
  • Everything inside a child template is compiled in the child scope;
  • The contents of the slot do not have access to the state 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 when it renders.

  • We can pass attributes on the outlet of a slot in the same way we pass props to components:

  • There is a small difference in how default slots and named slots are used when receiving slot props.

    • The default slot accepts props, and a slot props object is directly received through v-slotthe directive :
    <!-- <MyComponent> 的模板 -->
    <div>
      <slot :text="greetingMessage" :count="1"></slot>
    </div>
    
    <MyComponent v-slot="slotProps">
      {
         
         { slotProps.text }} {
         
         { slotProps.count }}
    </MyComponent>
    
    
    • Named scope slots work similarly, slot props can be accessed as the value of v-slotthe directive : v-slot:name="slotProps". When using abbreviations like this:
    <MyComponent>
      <template #header="headerProps">
        {
         
         { headerProps }}
      </template>
    </MyComponent>
    
    • Pass props to named slots:
    <slot name="header" message="hello"></slot>
    

Guess you like

Origin blog.csdn.net/qq_53664443/article/details/129754376