Vue Scoped Slots(范围插槽)

Scoped slot(范围插槽)提供来自组件的本地数据,以便父级可以选择如何渲染它。


发送数据到父级

我们在组件插槽中使用 v-bind 将本地数据发送到父级:

SlotComp.vue:

  1. <template>
  2. <slot v-bind:lclData="data"></slot>
  3. </template>
  4. <script>
  5. export default {
  6. data() {
  7. return {
  8. data: 'This is local data'
  9. }
  10. }
  11. }
  12. </script>

组件内部的数据可以称为 'local'(本地),因为除非像我们在这里使用 v-bind 那样将其发送到父级,否则父级无法访问该数据。


从范围 Slot 接收数据

组件中的本地数据使用 v-bind 发送,并且可以在带有 v-slot 的父级中接收:

实例

App.vue:

  1. <slot-comp v-slot:"dataFromSlot">
  2. <h2>{{ dataFromSlot.lclData }}</h2>
  3. </slot-comp>

在上面的实例中,'dataFromSlot' 只是一个我们可以自己选择的名称,用于表示我们从作用域插槽接收的数据对象。我们使用 'lclData' 属性从 slot 中获取文本字符串,并使用插值来最终呈现 <h2> 标记中的文本。


数组范围 Slot

范围 Slot 可以使用 v-for 从数组发送数据,但 App.vue 中的代码基本相同

实例

SlotComp.vue:

  1. <template>
  2. <slot
  3. v-for="x in foods"
  4. :key="x"
  5. :foodName="x"
  6. ></slot>
  7. </template>
  8. <script>
  9. export default {
  10. data() {
  11. return {
  12. foods: ['Apple','Pizza','Rice','Fish','Cake']
  13. }
  14. }
  15. }
  16. </script>

App.vue:

  1. <slot-comp v-slot="food">
  2. <h2>{{ food.foodName }}</h2>
  3. </slot-comp>

对象数组范围 Slot

范围 Slot 可以使用 v-for 从对象数组发送数据:

实例

SlotComp.vue:

  1. <template>
  2. <slot
  3. v-for="x in foods"
  4. :key="x.name"
  5. :foodName="x.name"
  6. :foodDesc="x.desc"
  7. :foodUrl="x.url"
  8. ></slot>
  9. </template>
  10. <script>
  11. export default {
  12. data() {
  13. return {
  14. foods: [
  15. { name: 'Apple', desc: 'Apples are a type of fruit that grow on trees.', url: 'img_apple.svg' },
  16. { name: 'Pizza', desc: 'Pizza has a bread base with tomato sauce, cheese, and toppings on top.', url: 'img_pizza.svg' },
  17. { name: 'Rice', desc: 'Rice is a type of grain that people like to eat.', url: 'img_rice.svg' },
  18. { name: 'Fish', desc: 'Fish is an animal that lives in water.', url: 'img_fish.svg' },
  19. { name: 'Cake', desc: 'Cake is something sweet that tastes good but is not considered healthy.', url: 'img_cake.svg' }
  20. ]
  21. }
  22. }
  23. }
  24. </script>

App.vue:

  1. <slot-comp v-slot="food">
  2. <hr>
  3. <h2>{{ food.foodName }}<img :src=food.foodUrl></h2>
  4. <p>{{ food.foodDesc }}</p>
  5. </slot-comp>

范围 Slot 的静态数据

范围 Slot 还可以发送静态数据,即不属于 Vue 实例的数据属性的数据。

在发送静态数据时,我们不使用 v-bind

在下面的例子中,我们发送一个静态文本,一个动态绑定到数据实例的文本,这样我们就可以看到差异。

实例

SlotComp.vue:

  1. <template>
  2. <slot
  3. staticText="This text is static"
  4. :dynamicText="text"
  5. ></slot>
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return {
  11. text: 'This text is from the data property'
  12. }
  13. }
  14. }
  15. </script>

App.vue:

  1. <slot-comp v-slot="texts">
  2. <h2>{{ texts.staticText }}</h2>
  3. <p>{{ texts.dynamicText }}</p>
  4. </slot-comp>

命名范围 Slots

可以命名范围 Slot。

要使用命名范围的插槽,我们需要使用 'name' 属性命名组件内的 slot。

要从命名 slot 接收数据,我们需要在使用组件的父级中引用该名称,并使用 v-slot 指令或简写 #

实例

在本例中,创建的组件一次引用 "leftSlot",一次引用时隙 "rightSlot"。

SlotComp.vue:

  1. <template>
  2. <slot
  3. staticText="This text is static"
  4. :dynamicText="text"
  5. ></slot>
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return {
  11. text: 'This text is from the data property'
  12. }
  13. }
  14. }
  15. </script>

App.vue:

  1. <slot-comp v-slot="texts">
  2. <h2>{{ texts.staticText }}</h2>
  3. <p>{{ texts.dynamicText }}</p>
  4. </slot-comp>

或者,我们可以使用两个不同的 "template" 标记一次性创建组件,每个 "template" 标记都指向不同的 slot。

实例

在本例中,组件只创建一次,但有两个 "template" 标记,每个标记都指向不同的 slot。

SlotComp.vue 与前面的实例完全相同。

App.vue:

  1. <slot-comp>
  2. <template #leftSlot="leftProps">
  3. <div>{{ leftProps.text }}</div>
  4. </template>
  5. <template #rightSlot="rightProps">
  6. <div>{{ rightProps.text }}</div>
  7. </template>
  8. </slot-comp>