Let's get to know the slot first
In development, we often encapsulate reusable components:
- Previously, we'll pass some data to the component through props so that it can be displayed.
- However, in order to make this component more versatile, we cannot restrict the contents of the component to fixed div, span, and so on.
- We should allow users to decide what content and elements to store in an area.
How to use slot?
- In fact, the process of using the slot is to extract common features and reserve different ones.
- We will still encapsulate the common elements and contents within the components.
- At the same time, slot s are used as placeholders for different elements, allowing the outside to decide what elements to display.
- In an encapsulated component, a slot can be opened for the encapsulated component using a special element.
- What the slot inserts depends on how the parent component is used;
Basic use of slots
App.vue
<template> <div> <my-slot-cpn> <button>I am a button</button> </my-slot-cpn> <my-slot-cpn> <my-input-cpn /> </my-slot-cpn> <h2>I am not a component of the slot</h2> <my-slot-cpn> <h4>Lots of stuff in the slot</h4> <i>Do you trust me?</i> <del>Come on.</del> </my-slot-cpn> <my-slot-cpn></my-slot-cpn> </div> </template> <script> import MySlotCpn from "./MySlotCpn.vue"; import MyInputCpn from "./MyInputCpn.vue"; export default { name: "App", components: { MySlotCpn, MyInputCpn }, methods: {}, }; </script> <style scoped> </style>
MySlotCpn.vue
<template> <div> <h3>Start of component</h3> <slot> <i>I am a slot, no information is filled in, I am the default</i> </slot> <h3>End of component</h3> </div> </template> <script> export default {}; </script> <style lang="scss" scoped> </style>
MyInputCpn.vue
<template> <div> <input type="text" placeholder="I'm an input box" /> </div> </template> <script> export default {}; </script> <style lang="scss" scoped> </style>
Use of named slots - dynamic slot names
- A named slot, as its name implies, gives the slot a name, and the element has a special attribute: name.
- A slot without a name, with the implied name default;
We can dynamically bind a name via v-slot:[dynamicSlotName];
Abbreviations for named slots:
Like v-on and v-bind, v-slot has abbreviations;
That is, replace everything before the parameter (v-slot:) with the character #;
<template> <div> <nar-bar :name="name"> <template v-slot:left> I am the slot on the left </template> <template v-slot:center>I am the middle slot</template> <template v-slot:right>I am the right slot</template> <template #[name]>I am a grammar sugar and dynamic slot </template> </nar-bar> </div> </template> <script> import NarBar from "./NarBar.vue"; export default { name: "App", data() { return { name: "lisi", }; }, components: { NarBar, }, }; </script>
<template> <div> <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 class="name"><slot :name="name"></slot></div> </div> </div> </template> <script> export default { props: { name: String, }, }; </script>
Render Scope
There is a concept of rendering scope in Vue:
- All content in the parent template is compiled in the parent scope;
- Everything in a sub-template is compiled in a sub-scope;
List
Understanding Scope Slot
But sometimes it is very important that we want the slot to have access to the contents of the subcomponents:
- When a component is used to render an array element, we use a slot, and we want the slot to display nothing for each item.
- This Vue provides us with a scoped slot;
Use steps
ShowNames.vue
<template> <div> <template v-for="(item, index) in names" :key="item"> <slot :item="item" :index="index"></slot> <slot name="lisi"></slot> </template> </div> </template> <script> export default { props: { names: { type: Array, default: () => [] } } } </script> <style scoped> </style>
App.vue
<template> <div> <nar-bar :name="name"> <template v-slot:left> I am the slot on the left </template> <template v-slot:center>I am the middle slot</template> <template v-slot:right>I am the right slot</template> <template #[name]>I am a grammar sugar and dynamic slot </template> </nar-bar> <hr /> <show-names :names="names"> <template v-slot="names"> <p>{{ names.item }}-{{ names.index }}</p> </template> </show-names> <hr /> // If we have default and named slots, then follow the full template <show-names :names="names"> <template v-slot="slotProps"> <span>{{ slotProps.item }}---{{ slotProps.index }}</span> </template> </show-names> <hr /> // If only the default slot is in our slot, the label of the component can be used as a template for the slot, so that we can use v-slot directly on the component <show-names :names="names" v-slot="slotProps"> <button>{{ slotProps.item }}-{{ slotProps.index }}</button> </show-names> <hr /> <show-names :names="names"> <template v-slot="slotProps"> <button>{{ slotProps.item }}-{{ slotProps.index }}</button> </template> //If our slot is default, v-slot:default="slotProps" can be abbreviated as V slot="slotProps" when used: <template v-slot:lisi> <h2>I am name Insertion of</h2> </template> </show-names> </div> </template> <script> import NarBar from "./NarBar.vue"; import ShowNames from "./ShowNames.vue"; export default { name: "App", data() { return { names: ["Zhang San", "Li Si", "King Five", "Zhao Six", "Sun Qi"], }; }, components: { NarBar, ShowNames, }, }; </script>