Vue 作用域插槽

从作用域槽接收数据

组件中本地数据用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: '此文本来自 data 属性'
      }
    }
  }
</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: '该文本属于 LEFT 槽。',
        rightText: '该文本属于 RIGHT 槽。'
      }
    }
  }
</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 练习

通过练习测试自己

练习题:

需要什么指令才能将数据从组件槽提供给父级?

组件中的本地数据从带有  的槽发送,
并且可以通过  在父级中接收。

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

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

开始练习