Slot slot

  • Slot effect: To make components more extensible. Extract the commonalities and reserve the differences as slots so that other components can pass the labels they want to display to the reserved slots.
  • <slot>The element acts as a content distribution slot in the component template.<slot>The element itself will be replaced

Basic use of slots

1. Basic use of slots

A slot is reserved in a component for external components to use and deliver content to the slot for display

<body>
    <div id="app">
        <cpn></cpn>
        <cpn>
          	<! -- Other components using the CPN component can pass their content to the CPN component slot -->
            <button>btn</button>
        </cpn>
    </div>

    <template id="cpn">
        <div>
            <p>I am a CPN component</p>
          	<! -- There is a slot in the CPN component so that it can be passed to the slot when the CPN component is used externally.
            <slot></slot>
        </div>
    </template>

    <script>
        new Vue({
            el: '#app'.components: {
                cpn: {
                    template: '#cpn'}}})</script>
</body>
Copy the code

2. Default value of the slot

If other components that use CPN components mostly pass button elements into the CPN component slot, then we can use the button element as the default for the slot; This eliminates the need to manually pass the button element every time you use it.

Default value rule: If any content is passed to the slot, the content passed by the user is displayed to the slot. If not, use the slot default value

// Example 1: without a default value<div id="app">
  <cpn></cpn>
  <cpn> <button>btn</button> </cpn>
  <cpn> <button>btn</button> </cpn>
  <cpn> <button>btn</button> </cpn>
</div>

<! -- CPN component -->
<template id="cpn">
  <div>
    <p>I am a CPN component</p>
    <slot></slot>
  </div>
</template>// Example 2: Extract to slot default values<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn></cpn>
  <cpn></cpn>
</div>

<! -- CPN component -->
<template id="cpn">
  <div>
    <p>I am a CPN component</p>
    <slot> <button>btn</button> </slot>
  </div>
</template>

Copy the code

3. Multi-value substitution

If multiple elements are transferred to a slot but only one slot is reserved, all the transferred elements are replaced by the reserved slot

/ / sample:<div id="app">
  <cpn></cpn>
  <! Button and input passed by CPN components will be replaced with reserved slots.
	<cpn>
    <button>btn</button>
    <input type="text">
  </cpn>
</div>

<template id="cpn">
  <div>
    <p>I am a CPN component</p>
    <slot></slot>
	</div>
</template>

Copy the code

A named slot

1.V-slot: Used to bind the specified slot (the name property of the slot component) in the child component template. Tags passed from the parent component to the child component are then bound to a specific slot for display2.V-slot can only be added to <template></template>.3.The abbreviation of v-slot is` # ` ('v-slot:center'Is equivalent to'#center' )
Copy the code

User-passed labels replace slots that do not have names by default

<! -- Example 1: The following shows that the passed button element replaces the three slots reserved for the CPN component with three buttons; Insert button element into 3 slots -->
<div id="app">
  <cpn> <button>btn</button> </cpn>
</div>

<template id="cpn">
  <div>
    <slot> <span>On the left</span> </slot>
    <slot> <span>In the middle</span> </slot>
    <slot> <span>On the right</span> </slot>
	</div>
</template>
Copy the code

If we want to replace the specified slot, we can wrap the parent with the template tag that the parent passes to the child, and we can bind the slot name in the child with the V-slot attribute on the template. See the following code for details:

<! -- Example 1: -->
<div id="app">
  <cpn>// Wrap the template label button that will be passed to the child CPN, and v-slot the slot reserved in the child CPN (v-slot the slot name attribute); The parent component's button can then be rendered to the CPN slot named Center<template v-slot:center>
          <button>btn</button>
      </template>
  </cpn>
</div>

<template id="cpn">
  <div>
    <slot name="left"> <span>On the left</span> </slot>
    <slot name="center"> <span>In the middle</span> </slot>
    <slot name="right"> <span>On the right</span> </slot>
	</div>
</template>
Copy the code

Compile scope

  • conclusionWhen using a variable, it is not clear which component the variable belongs to, and whose template the method is used in, the variable belongs to.
// VM instance component template; So the isShow variable used below is the VM instance's isShow variable instead of CPN's<div id="app">
  <cpn v-show="isShow"></cpn>
</div>// CPN component template<template id="cpn">
  <div>hello</div>
</template>
Copy the code

Scope slot

Summary: The parent component customizes the label that is displayed on the child component slot, but the data content of the label is provided by the child component. This requires the child to pass the data content to the parent.

1. The default slot of the scope slot

<! -- Example 1: -->
<body>// Parent component template<div id="app">
        <cpn>// In the template of the parent component, 'v-slot:default="slotProps" is used to obtain the data bound to the slots of the child component and store the data on the slotProps object. You can name the slotProps as you like<template v-slot:default="slotProps">
                <p>{{ slotProps.persons.join('--') }}</p>
            </template>
        </cpn>
    </div>// Subcomponent CPN template<template id="cpn">
        <div>// Bind the persons data of the child component to the slot of the child component, so that the parent component can obtain the data of the child component through the V-slot, and then use the data of the child component on the tag that the parent component passes to the child component<slot v-bind:persons="persons"></slot>
        </div>
    </template>

    <script>
        new Vue({
            el: '#app'.components: {
                cpn: {
                    template: '#cpn'.data() {
                        return {
                            persons: ['Invincible in the East'.Snow Chihiro.'Whatever I do'.Linghu Chong.'Jiu Mozhi'.'A lonely man seeking defeat']}},}}})</script>
</body>
Copy the code

2. Multiple slots of scope slots

If there is only one default slot, use v-slot:default=”slotProps”, the name of slotProps can be arbitrary. When multiple slots are present, you can name each slot with the name attribute, followed by v-slot:person=”slotPersonProps”, where person binds the name attribute of the slot tag in the subcomponent

// Example 1:<body>
    <div id="app">
        <cpn>
            <template v-slot:person="slotPersonProps">
                <p>{{ slotPersonProps.cpnperson  }}</p>
            </template>
            <template v-slot:book="slotBookProps">
                <p v-for="i in slotBookProps.cpnbook">{{ i }}</p>
            </template>
        </cpn>
    </div>

    <template id="cpn">
        <div>// Multiple slots use the name attribute, so that the parent component can obtain the data attribute of the child component bound to the slot specified by name via 'V-slot :name'<slot v-bind:cpnperson="persons" name="person"></slot>
            <slot v-bind:cpnbook="books" name="book"></slot>
        </div>
    </template>

    <script>
        new Vue({
            el: '#app'.components: {
                cpn: {
                    template: '#cpn'.data() {
                        return {
                            persons: ['Invincible in the East'.Snow Chihiro.'Whatever I do'.Linghu Chong.'Jiu Mozhi'.'A lonely man seeking defeat'].books: ['c++'.'js'.'pyhton'.'c'.'java']}},}}})</script>
</body>
Copy the code

Deconstructing slot prop

For multiple slots, it is possible to write a deconstructed slot prop

// Example 1:<body>
    <div id="app">
        <cpn>V-slot :person="slotPersonProps" = cpnPerson from the slotPersonProps object<template v-slot:person="{cpnperson}">
                <p>{{ cpnperson  }}</p>
            </template>
        </cpn>
    </div>

    <template id="cpn">
        <div>
            <slot v-bind:cpnperson="persons" name="person"></slot>
        </div>
    </template>

    <script>
        new Vue({
            el: '#app'.components: {
                cpn: {
                    template: '#cpn'.data() {
                        return {
                            persons: ['Invincible in the East'.Snow Chihiro.'Whatever I do'.Linghu Chong.'Jiu Mozhi'.'A lonely man seeking defeat'].books: ['c++'.'js'.'pyhton'.'c'.'java']}},}}})</script>
</body>

Copy the code

Vue slot usage case