插槽在Vue项目中至关重要,它支持我们在使用UI组件或者自定义组件时可以实现在子组件DOM中插入一些我们想要自定义的内容,也可以把父组件的数据显示在子组件中,这是我们在做自定义组件时必须要考虑的可扩展性的重要一环。
Vue组件中的插槽是利用 slot 标签实现,该标签会被插槽函数调用,拿到我们在父组件自定义的内容,将其渲染在子组件的槽位中。
1、默认插槽
默认插槽也被称作匿名插槽,此类插槽在子组件定义时不需要命名,在外部使用中也不需要声明就可以直接使用 slot 元素即可。
子组件:
<template>
<div>
<slot></slot>
</div>
</template>
当然,如果我们需要的话,也可以给插槽定义一些默认内容,如果父组件没有传入内容时,则会展示我们定义的默认内容。
<template>
<div>
<slot>
<h4>我是默认内容</h4>
</slot>
</div>
</template>
父组件:
import DefaultSlot from './components/DefaultSlot.vue'
<template>
<div>
<h1>我是父组件</h1>
<DefaultSlot>
<h2>我要子组件展示这里的内容</h2>
</DefaultSlot>
<!-- 没有命名的插槽会被隐式命名为:default,所以也可以具名使用 -->
<DefaultSlot>
<template #default>
<h2>我跟上一种方式结果一致</h2>
</template>
</DefaultSlot>
</div>
</template>
2、具名插槽
具名插槽也被称作命名插槽,当我们需要在同一个组件命名多个插槽时,我们就可以给每一个 slot 标签命名一个名字,插槽函数就根据定义好的名字填充到对应的位置了。
子组件:
<template>
<div>
<slot name="header">
<div>我是header</div>
</slot>
<slot>
<div>我是默认内容</div>
</slot>
<slot name="footer">
<div>我是footer</div>
</slot>
</div>
</template>
父组件:
import NameSlot from './components/NameSlot.vue'
<template>
<div>
<h1>我是父组件</h1>
<NameSlot>
<template v-slot:header>
<h4>我是 header</h4>
</template>
<h4>我是主体内容</h4>
<template #footer>
<h4>我是 footer</h4>
</template>
</NameSlot>
</div>
</template>
3、条件插槽
有时我们需要根据插槽是否存在来渲染某些内容,结合使用 $slots 与 v-if 来实现这个条件插槽
子组件:
<template>
<div>
<div v-if="$slots.header">
<slot name="header"></slot>
</div>
<div v-if="$slots.default">
<slot></slot>
</div>
<div v-if="$slots.footer">
<slot name="footer"></slot>
</div>
</div>
</template>
父组件:
<template>
<div>
<h1>我是父组件</h1>
<ConditionalSlot>
<template #header>
<div>我是头部组件哦</div>
</template>
<div>我是主体组件哦</div>
</ConditionalSlot>
</div>
</template>
4、动态插槽
动态插槽就是插槽名字变成了变量,可以随时修改这个变量以达到不一样的展示效果,可以通过 v-slot:[变量名] 或者 #[变量名] 来实现动态插槽
子组件:
<template>
<div>
<slot name="header"></slot>
</div>
</template>
父组件:
<template>
<div>
<h1>我是父组件</h1>
<DynamicSlot #[dynamicSlotName]></DynamicSlot>
</div>
</template>
5、作用域插槽
有时候我们需要在父组件自定义插槽内容时,会需要用到子组件的数据来展示,此时就需要作用域插槽来将数据传出,我们需要在父组件的标签中通过 v-slot=“传过来的数据” 来接受数据即可。
子组件:
<template>
<div>
<slot myname="小陆" myage="18"></slot>
</div>
</template>
父组件:
import ScopeSlot from './components/ScopeSlot.vue'
<template>
<div>
<h1>我是父组件</h1>
<ScopeSlot>
<template v-slot="propsData">
<div style="color: #c236ec">
<span>我叫{{ propsData.myname }},</span>
<span>今年{{ propsData.myage }}岁</span>
</div>
</template>
<!-- 我还可以解构哦 -->
<template v-slot="{ myname, myage }">
<div style="color: #2c91c0">
<span>我叫{{ myname }},</span>
<span>今年{{ myage }}岁</span>
</div>
</template>
</ScopeSlot>
</div>
</template>
6、具名作用域插槽
子组件:
<template>
<div>
<slot name="info" myname="小陆" myage="18"></slot>
</div>
</template>
父组件:
import ScopeNameSlot from './components/ScopeNameSlot.vue'
<template>
<div>
<h1>我是父组件</h1>
<ScopeNameSlot>
<template #info="{ myname, myage }">
<div style="color: #2c91c0">
<span>我叫{{ myname }},</span>
<span>今年{{ myage }}岁</span>
</div>
</template>
</ScopeNameSlot>
</div>
</template>