1. Default slot
1. Code demonstration
Through the above code, we understand at least the following two points:
1. The slot can have default content,
2. The default slot, The content of the component will all be replaced in the slot
2. The data of the parent component can also be displayed in the child component (the scope of the data will be used later in the scope slot)
2. Grammar
fixed tank:<slot>插槽的默认内容</slot>
Using tank:<组件> 内容全部替换到插槽中 </组件>
2. Named slot
1. Code demonstration
Named slot: To understand simply, it is to name each
<slot>
to distinguish it.
Note: The default slot also hasname
,name='default'
2. Grammar
fixed tank:<slot name="one"></slot>
Using tank:<template v-slot:one> <div>{
{ msg }}</div> </template>
Short copy:<template #one> <div>{
{ msg }}</div> </template>
3. Dynamic slot name
Dynamic slot name:
The slot names defined now are all hard-coded, and Vue also supports defining slot names as variables.
fixed tank:<slot :name="name"></slot>
Using tank:<template #[name]> <div>动态插槽名</div> </template>
3. Scope slot
1. Rendering scope
Rendering scope:
All content in the parent template is compiled in the parent scope
All content in the child template They are all compiled in child scopes
Therefore, a problem also arises:
Assume that in the first scenario, you need to write a product card component and display multiple cards through a loop,
And it is required to jump to the product details page in response to the click event on each card. How would you write it?
I would use the following processing method,
- First write the product card as a component
card.vue
,- Use one in
cardList.vue
to handle the display of the product card list.v-for
card.vue
The component passes$emit
to the parent componentcardClick
and carries product data,- The parent component can obtain the data in the
onClick
method and perform business processing,- This completes a basic data transfer from child to parent.
// cardList.vue
<template>
<div class="card">
<Card v-for="item in cardData" :key="item" @cardClick="onClick()"></Card>
</div>
</template>
// card.vue
<template>
<div class="div" @click="onClick()">卡片</div>
</template>
<script>
export default {
methods: {
onClick () {
this.$emit('cardClick')
}
}
}
</script>
What if we abstract it further?
For example, if there are multiple operating columns, such as the Taobao homepage has two columns: "Have Good Products" and "Love Shopping", each column needs to have a list of product cards, then the product card ListcardList.vue
is about to draw components. As for this vue component that contains multiple operating columns, I assume it is called finalList.vue
, in which the component is called through v-for
. cardList.vue
Note:
Here comes the demand—>I hope to handle the business of clicking on product cards infinalList.vue
. How to deal with it?
method 1:
- When the product button is clicked,
card.vue
For configuration$emit
NotificationcardList.vue
,cardList.vue
Continue to use$emit
Toss up, notifyfinalList.vue
finalList.vue
Use event reception and processing.
There is absolutely no problem in doing this, but it seems that the sub-component is very impure and has nothing to do with the business.
2. Scope slot (practical application)
So how to solve the above problem elegantly? At this time, the scope slot really comes in handy.
Let’s first look at how to solve the above problem through scope slots.
(1)finalList.vue
// src\views\06slot\finalList.vue
<template>
<div>
<div v-for="item in '123'" :key="item">
<div style="text-align: left;">第{
{ item }}个</div>
<CardList :cardData="cardData" class="cardlist">
<template v-slot="scope">
<Card :cardObj="scope.row" @click.native="cardClick(scope.row)" class="card"></Card>
</template>
</CardList>
</div>
</div>
</template>
<script>
import Card from './card.vue'
import CardList from './cardList.vue'
export default {
components: {
Card,
CardList
},
data () {
return {
cardData: [
{
name: 'zs', age: 18 },
{
name: 'ls', age: 19 }
]
}
},
methods: {
cardClick (row) {
console.log('卡片点击了:' + row.name + '--' + row.age)
}
}
}
</script>
<style scoped>
.cardlist {
display: flex;
}
.card {
margin: 10px 20px;
}
</style>
(2)cardList.vue
// src\views\06slot\cardList.vue
<template>
<div>
<div v-for="(item, index) in cardData" :key="index">
<slot :row="item"></slot>
</div>
</div>
</template>
<script>
export default {
props: {
cardData: {
type: Array
}
}
}
</script>
<style scoped>
</style>
(3)card.view
// src\views\06slot\card.vue
<template>
<div class="div">
<div>{
{ cardObj.name }}</div>
<div>{
{ cardObj.age }}</div>
</div>
</template>
<script>
export default {
props: {
cardObj: {
type: Object,
default: () => {
}
}
}
}
</script>
<style scoped>
.div {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
(4) Final effect
summary
About scope slots:
Simple understanding: Scope slots are简化
subcomponents passing $emit to parent components< a i=3>Another representation of data Applicable scenarios: It contains at least three levels of component levels, which is an excellent componentization solution!多层传递
3. Simple application demo
- The parent component accesses the data of the child component:
- The parent component obtains the component slot attribute:
v-slot="slotProps"
, - Child components bind data into dynamic properties:
<slot :item="item"></slot>
- The parent component obtains the component slot attribute:
- Display data in the form expected by the parent component:
- Define slot slot in subcomponent:
<slot :item="item" :index="index"></slot>
- The parent component replaces the slot content of the child component through the slot.
- Define slot slot in subcomponent:
4. Multi-layer nesting of slots
1. Demand
There are three components A, B, and C. The content of the slot of component A is passed to component B, and component B is passed to component C.
2. Code demonstration
// src\views\06slot\parent.vue
<template>
<div>
<Children1>
<template v-slot:one>
<div>根节点信息</div>
</template>
</Children1>
</div>
</template>
// src\views\06slot\children1.vue
<template>
<div>
<div>children1</div>
<Children2>
<slot name="one" slot="two"></slot>
</Children2>
</div>
</template>
// src\views\06slot\children2.vue
<template>
<div>
<div>children2</div>
<slot name="two"></slot>
</div>
</template>
3. Code effect
4. Core points
- A component uses
v-slot:one
to pass content to B component - B component uses
name="one"
to receive the content of the slot, and passes the content to C component throughslot="two"
. That is:<slot name="one" slot="two"></slot>
- C component uses
<slot name="two"></slot>
to receive the content of A component