范围插槽

作用域插槽提供来自组件的本地数据,以便父级可以选择如何渲染它。

发送数据给父级

我们用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

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

示例

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>
运行示例 »

Vue练习

通过练习测试一下

练习:

需要哪些指令来将数据从组件槽提供给父级?

Local data in a component is sent from a slot with , 
and it can be received in the parent with .

CompOne.vue:
<slot :lclData="data"></slot>

App.vue:
<comp-one :"dataFromSlot">
  <h2>{{ dataFromSlot.lclData }}</h2>
</comp-one>

开始练习