作用域插槽
作用域插槽 提供组件的本地数据,以便父组件可以选择如何渲染它。
将数据发送给父组件
我们在组件的插槽中使用 v-bind 来将本地数据发送给父组件。
SlotComp.vue:
<template>
<slot v-bind:lclData="data"></slot>
</template>
<script>
export default {
data() {
return {
data: 'This is local data'
}
}
}
</script>
组件内部的数据可以被认为是“本地的”,因为除非将其发送到父组件,否则父组件无法访问它,就像我们这里使用 v-bind 所做的那样。
从作用域插槽接收数据
组件中的本地数据通过 v-bind 发送,并且可以在父组件中使用 v-slot 接收。
示例
App.vue:
<slot-comp v-slot:"dataFromSlot">
<h2>{{ dataFromSlot.lclData }}</h2>
</slot-comp>
运行示例 »
在上面的示例中,“dataFromSlot” 只是一个我们可以自己选择的名称,用来表示我们从作用域插槽接收到的数据对象。我们通过“lclData” 属性获取来自插槽的文本字符串,并使用插值最终在一个 <h2> 标签中渲染该文本。
带数组的作用域插槽
作用域插槽可以通过使用 v-for 来发送数组数据,但 App.vue 中的代码基本相同。
示例
SlotComp.vue:
<template>
<slot
v-for="x in foods"
:key="x"
:foodName="x"
></slot>
</template>
<script>
export default {
data() {
return {
foods: ['Apple','Pizza','Rice','Fish','Cake']
}
}
}
</script>
App.vue:
<slot-comp v-slot="food">
<h2>{{ food.foodName }}</h2>
</slot-comp>
运行示例 »
带对象数组的作用域插槽
作用域插槽可以通过使用 v-for 来发送对象数组的数据。
示例
SlotComp.vue:
<template>
<slot
v-for="x in foods"
:key="x.name"
:foodName="x.name"
:foodDesc="x.desc"
:foodUrl="x.url"
></slot>
</template>
<script>
export default {
data() {
return {
foods: [
{ name: 'Apple', desc: 'Apples are a type of fruit that grow on trees.', url: 'img_apple.svg' },
{ name: 'Pizza', desc: 'Pizza has a bread base with tomato sauce, cheese, and toppings on top.', url: 'img_pizza.svg' },
{ name: 'Rice', desc: 'Rice is a type of grain that people like to eat.', url: 'img_rice.svg' },
{ name: 'Fish', desc: 'Fish is an animal that lives in water.', url: 'img_fish.svg' },
{ name: 'Cake', desc: 'Cake is something sweet that tastes good but is not considered healthy.', url: 'img_cake.svg' }
]
}
}
}
</script>
App.vue:
<slot-comp v-slot="food">
<hr>
<h2>{{ food.foodName }}<img :src=food.foodUrl></h2>
<p>{{ food.foodDesc }}</p>
</slot-comp>
运行示例 »
来自作用域插槽的静态数据
作用域插槽也可以发送静态数据,即不属于 Vue 实例 data 属性的数据。
发送静态数据时,我们不使用 v-bind。
在下面的示例中,我们发送了一个静态文本,以及一个动态绑定到 data 实例的文本,这样我们就可以看到区别。
示例
SlotComp.vue:
<template>
<slot
staticText="This text is static"
:dynamicText="text"
></slot>
</template>
<script>
export default {
data() {
return {
text: 'This text is from the data property'
}
}
}
</script>
App.vue:
<slot-comp v-slot="texts">
<h2>{{ texts.staticText }}</h2>
<p>{{ texts.dynamicText }}</p>
</slot-comp>
运行示例 »
命名作用域插槽
作用域插槽可以被命名。
要使用命名的作用域插槽,我们需要使用“name”属性在组件内部命名插槽。
要接收来自命名插槽的数据,我们需要在父组件使用该组件的地方,通过 v-slot 指令或简写 # 来引用该名称。
示例
在此示例中,组件被创建一次,引用插槽“leftSlot”,然后再次创建,引用插槽“rightSlot”。
SlotComp.vue:
<template>
<slot
name="leftSlot"
:text="leftText"
></slot>
<slot
name="rightSlot"
:text="rightText"
></slot>
</template>
<script>
export default {
data() {
return {
leftText: 'This text belongs to the LEFT slot.',
rightText: 'This text belongs to the RIGHT slot.'
}
}
}
</script>
App.vue:
<slot-comp #leftSlot="leftProps">
<div>{{ leftProps.text }}</div>
</slot-comp>
<slot-comp #rightSlot="rightProps">
<div>{{ rightProps.text }}</div>
</slot-comp>
运行示例 »
或者,我们可以只创建一次组件,使用两个不同的 "template" 标签,每个 "template" 标签引用一个不同的插槽。
示例
在此示例中,组件只创建一次,但有两个 "template" 标签,每个标签都引用一个不同的插槽。
SlotComp.vue 与前一个示例中的完全相同。
App.vue:
<slot-comp>
<template #leftSlot="leftProps">
<div>{{ leftProps.text }}</div>
</template>
<template #rightSlot="rightProps">
<div>{{ rightProps.text }}</div>
</template>
</slot-comp>
运行示例 »