Vue 插槽

66 阅读1分钟

让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件

1.默认插槽

父组件中:
<Category>
   <div>html结构1</div>
</Category>
子组件中:
<template>
    <div>
       <!-- 定义插槽 -->
       <slot>插槽默认内容...</slot>
    </div>
</template>
<script>
    export default {
            name:'Category',
            props:['title'],
            data() {},
    }
</script>

2.具名插槽

当一个组件中需要使用多个插槽时,<slot> 元素有一个特殊的 attribute:name。这个 attribute 可以用来定义额外的插槽:

<div class="container">
    <header>
        <slot name="header"></slot>
    </header>
    <main>
        <!-- 不加 name 属性,则 name 默认为default-->
        <slot></slot>
    </main>
    <footer>
        <slot name="footer"></slot>
    </footer>
</div>

在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

<base-layout>
  <!-- <template> 元素中的所有内容都将会被传入相应的插槽 -->
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>
  <!-- 任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。 -->
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <!-- 也可以使用 <template v-slot:default> </template> 包裹默认插槽的内容
  <template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template> -->

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

3.作用域插槽

  1. 理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)

子组件中:

<template>
 <div>
     <!-- 绑定在 `<slot>` 元素上的 attribute 被称为**插槽 prop -->
     <slot :games="games"></slot>
 </div>
</template>

<script>
 export default {
     name:'Category',
     props:['title'],
     //数据在子组件自身
     data() {
         return {
             games:['红色警戒','穿越火线','劲舞团','超级玛丽']
         }
     },
 }
</script>
                 

然后在父组件中接收传过来的值:

<Category title="游戏">
    <!-- 在父组件中,我们可以用 v-slot 设置一个任意值来定义我们提供的插槽 prop 的名字,然后直接使用就好了 -->
    <template v-slot:default="scope">
        <ul>
            <li v-for="(g,index) in scope.games" :key="index">{{g}}</li>
        </ul>
    </template>
</Category>

独占默认插槽的缩写语法

在上述情况中,父组件只含有默认插槽时,组件标签直接当作插槽的模板来使用

<Category title="游戏" v-slot:default="scope">
    <ul>
        <li v-for="(g,index) in scope.games" :key="index">{{g}}</li>
    </ul>
</Category>

同时,v-slot不带参数被假定为默认插槽,所以还可以简化为:

<Category title="游戏" v-slot="scope">
    <ul>
        <li v-for="(g,index) in scope.games" :key="index">{{g}}</li>
    </ul>
</Category>

当同时含有多个插槽时,必须使用使用完整的基于 <template> 的语法:

<Category title="游戏">
    <template v-slot:default="scope">
        <ul>
            <li v-for="(g,index) in scope.games" :key="index">{{g}}</li>
        </ul>
    </template>
    <template v-slot:other="otherScope">
        ...
    </template>
</Category>

解构插槽Prop

上述还可以写成:

<Category title="游戏">
    <template v-slot:default="{games}">
        <ul>
            <li v-for="(g,index) in games" :key="index">{{g}}</li>
        </ul>
    </template>
</Category>

还可以将 games 重命名为gameList

<Category title="游戏">
    <template v-slot:default="{games:gameList}">
        <ul>
            <li v-for="(g,index) in gameList" :key="index">{{g}}</li>
        </ul>
    </template>
</Category>