让父组件可以向子组件指定位置插入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.作用域插槽
- 理解:
数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(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>