概述:
官网是这样说的:Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将
<slot>
元素作为承载分发内容的出口。可以理解为: slot就是可以在组件中添加内容,当组件layout都差不多的时候,需要改动小地方就使用它
单个插槽 | 匿名插槽
//大盒子组件
<template>
<div class="big_box">
<small-box>插入小盒子的内容</small-box>
</div>
</template>
//小盒子组件
<template>
<div class="small_box">
<slot></slot>
</div>
</template>
咱们在大盒子里给小盒子插入一句话“ 插入小盒子的内容”,小盒子在需要接收的地方写上<slot>标签。当组件渲染的时候,slot标签就会被替换成咱们插入的内容
不过,字符串只是开始!插槽还可以包含任何模板代码,包括 HTML以及其他的组件
<template>
<div class="big_box">
<small-box>
插入小盒子的内容
<a href="#">这是一个a标签</a>
<the-button></the-button>
</small-box>
</div>
</template>
编译作用域
当咱们想在插槽使用数据的时候可以直接调用大盒子里面的数据注入插槽中渲染
<template>
<div class="big_box">
<small-box>
插入小盒子的内容
{{num}}
</small-box>
</div>
</template>
<script>
import SmallBox from "./SmallBox.vue";
export default {
components: {
SmallBox
},
data(){
return{
num:666
}
}
}
</script>
当咱们使用小盒子中数据时会报错
<template>
<div class="big_box">
<small-box>
插入小盒子的内容
{{num}}
{{smallString}}
</small-box>
</div>
</template>
注意 :父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
默认内容
有时为一个插槽指定备用 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。例如在一个 <small-box> 组件中:
<template>
<div class="small_box">
<slot>添加默认内容</slot>
</div>
</template>
当咱们在其他组件引用此组件不加任何内容的时候,small-box组件会默认渲染上图中的文字
<template>
<div class="big_box">
<small-box>
覆盖内容
</small-box>
</div>
</template>
如果咱们提供内容给小盒子,那么小盒子里的“添加默认内容会被覆盖”
具名插槽
有时我们需要多个插槽,对于这样的情况,<slot>
元素有一个特殊的 attribute:name
。通过它可以为不同的插槽分配独立的 ID,也就能够以此来决定内容应该渲染到什么地方:
<template>
<div class="small_box">
<slot name='one'> 这就是默认值1</slot>
<slot name='two'> 这就是默认值2 </slot>
<slot name='three'> 这就是默认值3 </slot>
</div>
</template>
一个不带 name
的 <slot>
出口会带有隐含的名字“default”。在向具名插槽提供内容的时候,我们可以在一个 <template>
元素上使用 v-slot
指令,并以 v-slot
的参数的形式提供其名称:
<template v-slot:one> 这是插入到one插槽的内容 </template>
<template v-slot:two> 这是插入到two插槽的内容 </template>
<template v-slot:three> 这是插入到three插槽的内容 </template>
作用域插槽
通过slot 我们可以在父组件为子组件添加内容,通过给slot命名的方式,我们可以添加不止一个位置的内容。但是我们添加的数据都是父组件内的。上面我们说过不能直接使用子组件内的数据,但是我们是否有其他的方法,让我们能够使用子组件的数据呢? 其实我们也可以使用slot-scope。
<template>
<div class="small_box">
<slot name='one' :color1='color1'> 这就是默认值1</slot>
<slot name='two'> 这就是默认值2 </slot>
<slot name='three'> 这就是默认值3 </slot>
</div>
</template>
<script>
export default {
data () {
return {
smallString: '小盒子数据',
color1:"黄色",
color2:"绿色",
color3:"蓝色",
}
}
}
</script>
给具名插槽one绑定data中的数据color1
<template>
<div class="big_box">
<small-box>
<template v-slot:one="row"> 这是插入到one插槽的内容 {{row.color1}}</template>
<template v-slot:two> 这是插入到two插槽的内容 </template>
<template v-slot:three> 这是插入到three插槽的内容 </template>
</small-box>
</div>
</template>
然后再big_box组件中给小盒子添加插槽的地方用v-slot接收传到大盒子的数据,接收的名字可以自己定义,语义化更好(我这里写的是row),这样传过来之后就可以在template模板中使用数据了。
让我们来看看row打印出什么
打印出 row传过来的是对象,如果觉得row.color1写得手累,这时候咱们可以把props结构出来效果是一样的
<template>
<div class="big_box">
<small-box>
<template v-slot:one="{color1}"> 这是插入到one插槽的内容 {{color1}}
</template>
<template v-slot:two> 这是插入到two插槽的内容 </template>
<template v-slot:three> 这是插入到three插槽的内容 </template>
</small-box>
</div>
</template>
为了更懒一点,插槽v-slot我们可以缩写成#
<template>
<div class="big_box">
<small-box>
<template #one="{color1}"> 这是插入到one插槽的内容 {{color1}}
</template>
<template v-slot:two> 这是插入到two插槽的内容 </template>
<template v-slot:three> 这是插入到three插槽的内容 </template>
</small-box>
</div>
</template>
完全没有问题,又可以少按几下键盘了