Vue slots are classified into three types: anonymous slots, named slots, and scope slots

For example, create the following file:

  • Child-vue: encapsulates the component whose name is ChildExample

  • Parent. vue: Introduce child.vue and call ChildExample

Anonymous slot

is the most commonly used slot and can be customized as required

// child.vue <slot></slot> // parent-vue <child-example> <span> This is the content of the anonymous slot </span> </child-example>Copy the code

A named slot

If one slot is not sufficient and multiple slots are set, it is necessary to assign a name value

Note: An anonymous slot is a special named slot whose name is default. Avoid the same name!

// child.vue <slot name="left"></slot> <slot name="right"></slot> // parent.vue <child-example> <span < span style =" box-sizing: border-box! Important; word-wrap: break-word! Important;" -- 2.6.0 + --> <span> <span> </span> </template> </child-example>Copy the code

Scope slot

V-slot :slotName=”slotProps” instead of slot + slot-scope

// child.vue <slot name="demo" :data="list" :param="option"></slot> // parent.vue <child-example> <! - server + - > < template v - slot: demo = "{data, param}" > < span > {{data}} {{param}} < / span > < / template > <! -- or slot+slot-scope --> <! -- <span slot="demo" slot-scope="someProps">{{someProps.data}}{{someProps.param}}</span> --> </child-example>Copy the code

⚠ ️ please note

  1. Slot and slot-scope are still supported in Vue 2.x, but are officially deprecated and do not appear in Vue 3. The V-slot directive is recommended

  2. The V-slot directive can only be applied to template or custom components

When only the default slot is provided, the component’s label can be used as a template for the slot, allowing v-slot to be used directly on the component (shorthand syntax for exclusive default slot).

  1. V-slots with the same slot name overwrite the slots

  2. Slot name is the same as the slot contents, the latter overriding the former

  3. Slot compilation scope: Compilation scope

    • Everything in the parent template is compiled at the parent scope;

    • Everything in a subtemplate is compiled in the subscope

$slots & $scopedSlots

The official description of the two apis related to slots is as follows:

use$slotsand$scopedSlotsPackaging components

Encapsulate a to-do component: encapsulated in todolist.vue, invoked in demo.vue

Methods a

The slot is not used, todolist.vue is as follows:

<template> <ul> <li v-for="(item, index) in list" :key="index"> <span>{{item. Date}} : </span> {{ item.thing }} </li> </ul> </template> <script> export default { name: "todoList", props: { list: { type: Array, default() { return []; }}}}; </script>Copy the code

Introduce todolist.vue in demo.vue and call:

<template> <div id="demo"> <todo-list :list="data"></todo-list> </div> </template> import todoList from "src/components/todoList"; export default { name: "Demo", components: {todoList}, data() { return { data: [ { date: "Monday", thing: "Working" }, { date: "Tuesday", thing: "Working" }, { date: "Wednesday", thing: "Working" }, { date: "Thursday", thing: "Working" }, { date: "Friday", thing: "Working" }, { date: "Saturday", thing: "Vacation" }, { date: "Sunday", thing: "Vacation" } ], }; }};Copy the code

Effect – >


Method 2

Alternative implementation: Access $slots (known: Access $slots is good for writing components using rendering functions)

According to the data, it can be seen that 7 slots need to be set, and the name corresponds to the value of date. Here, add one knowledge point:

V-slot Supports dynamic slot names. The syntax is as follows: V-slot :[dynamicSlotName]

Therefore, todolist.vue is changed to:

<template> <todoItem></todoItem> </template> <script> export default { name: "todoList", components: { todoItem: { render(h) { let root = this.$parent; const {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday} = root.$slots; return h("ul", [ h("li", Monday), h("li", Tuesday), h("li", Wednesday), h("li", Thursday), h("li", Friday), h("li", Saturday), h("li", Sunday) ]); }}}}; </script>Copy the code

Change the demo. Vue call to:

<todo-list>
  <template v-for="(item, index) in data" v-slot:[item.date]>
    <p :key="index">
      <span>{{ item.date }} --- </span>
      <span style="color:#aaa">{{ item.thing }}</span>
    </p>
  </template>
</todo-list>
Copy the code

Effect – >


Methods three

In fact, method two is not often written this way. More often, it is an Element-Tree component that can either use the default Tree node style or customize the node content as needed.

The todo component wants to do the same, assuming that the todo data needs custom content for two days at the end of the week, you can use the scope slot to do this:

Change the data to specify the target slotName with the slotName attribute

{ date: "Saturday", thing: "Vacation", slotName: "weekend" },
{ date: "Sunday", thing: "Vacation", slotName: "weekend" }

Copy the code

In contrast to method 1, demo.vue adds the write target slot (weekend)

<todo-list :list="data2"> <template v-slot:weekend="item"> <p style="color:#ff9948"> <span>{{ item.date }} --- </span>{{  item.thing }}!!! Have a good day! </p> </template> </todo-list>Copy the code

Todolist. vue needs to determine the slotName attribute: If there is slotName attribute, then it will be rendered to get the custom slot contents by accessing $scopedSlots

<template> <ul> <li v-for="(item, index) in list" :key="index"> <! -- None slotName --> <template v-if="! "> <span>{{item.date}} : </span> {{item.thing}} </template> <! </scopeItem> </li> </ul> </template> <script> export default {name: "todoList", components: { scopeItem: { props: { option: { required: true } }, render(h) { const {root: $parent, option} = this; return root.$scopedSlots[option.slotName](option); } } }, props: { list: { type: Array, default() { return []; }}}}; </script>Copy the code

Effect – >

$scopedSlots[option.slotname](option) (call $scopedSlots. Weekend)

If I console you, the output is of typefunction:

Last but not least

If there is anything wrong, please let me know