插槽
插槽 (Slot) 是 vue 为组件的封装者提供的能力,允许开发者在封装组件时,把不确定的,希望由用户指定的部分定义为插槽
在封装组件的时候,可以在组件当中使用 slot 标签声明插槽的位置
<template>
<div class="left-container">
<h3>Left 组件</h3>
<hr>
<!-- 声明一个插槽区域 -->
<!-- vue 官方规定 每一个 slot 插槽 都要有一个 name 名称 -->
<!-- 如果省略了 slot 的 name 属性 则有一个默认名称叫做 default -->
<slot name="default"></slot>
</div>
</template>
v-slot指令
在需要将内容填充到指定名称的插槽中时,可以使用 v-slot: 这个指令
示例代码如下:
<Left>
<!-- 默认情况下 在使用组件的时候 提供的内容会被填充到名字为 default 的插槽之中 -->
<template v-slot:default>
<p>这是在 Left 组件的内容区域声明的 p 标签</p>
</template>
</Left>
template标签只作为一个虚拟的元素,在最终渲染页面的时候不会生成任何元素
v-slot: 后面要跟上插槽的名字
v-slot: 指令不能直接用来元素身上,必须用在 template 标签上
template 是一个虚拟的标签,只起到包裹性质的作用,不会被渲染成任何实质性的 HTML 元素
v-slot的简写
v-slot 的简写形式为 "#",代码示例如下:
<Left>
<!-- 默认情况下 在使用组件的时候 提供的内容会被填充到名字为 default 的插槽之中 -->
<template #default>
<p>这是在 Left 组件的内容区域声明的 p 标签</p>
</template>
</Left>
插槽的后备内容
封装组件时,可以为预留的 <slot> 插槽提供后备内容 (默认内容), 如果组件的使用者没有为插槽提供任何内容,则后备内容会生效,示例代码如下:
<template>
<div class="left-container">
<h3>Left 组件</h3>
<hr>
<!-- 声明一个插槽区域 -->
<!-- vue 官方规定 每一个 slot 插槽 都要有一个 name 名称 -->
<!-- 如果省略了 slot 的 name 属性 则有一个默认名称叫做 default -->
<slot name="default">default 插槽的默认内容</slot>
</div>
</template>
具名插槽
在定义组件且需要预留多个插槽位置的时候,需要给每个 插槽slot 设置不同的 name 属性
<template>
<div class="article-container">
<!-- 文章的标题 -->
<div class="header-box">
<slot name="title"></slot>
</div>
<!-- 文章的内容 -->
<div class="content-box">
<slot name="content"></slot>
</div>
<!-- 文章的作者 -->
<div class="footer-box">
<slot name="footer"></slot>
</div>
</div>
</template>
使用例子:
<Article>
<template #title>
<h3>title</h3>
</template>
<template #content>
<div>
<p>第一行内容</p>
<p>第二行内容</p>
<p>第三行内容</p>
</div>
</template>
<template #footer>
<h3>footer</h3>
</template>
</Article>
作用域插槽
在封装组件时,为预留的 slot 提供属性对应的值,这种做法叫做 "作用域插槽"
定义方法:
<template>
<div class="article-container">
<div class="content-box">
<!-- 在封装组件时 为预留的 slot 提供属性对应的值 这种做法叫做 作用域插槽 -->
<slot name="content" msg="Hello vue"></slot>
</div>
</div>
</template>
使用方法:
<Article>
<template #content="obj">
<div>
<p>{{ obj.msg }}</p>
</div>
</template>
</Article>
此处的 obj 相当于形参,可以自行起名,但建议规范写法为 "scope"
作用于插槽的解构赋值
在使用作用域插槽的数据的时候,可以在接收数据时使用解构赋值直接获取数据
代码示例:
// app.vue
<template #content="{msg, user}">
<div>
<p>第一行内容</p>
<p>第二行内容</p>
<p>第三行内容</p>
<p>{{ msg }}</p>
<p>{{ user.name }}</p>
</div>
</template>
// article.vue
<template>
<div class="article-container">
<!-- 文章的标题 -->
<div class="header-box">
<slot name="title"></slot>
</div>
<!-- 文章的内容 -->
<div class="content-box">
<!-- 在封装组件时 为预留的 slot 提供属性对应的值 这种做法叫做 作用域插槽 -->
<slot name="content" msg="Hello vue" :user="userinfo"></slot>
</div>
<!-- 文章的作者 -->
<div class="footer-box">
<slot name="footer"></slot>
</div>
</div>
</template>
<script>
export default {
// 首字母大写
name: "Article",
data() {
return {
userinfo: {
name: 'zs',
age: 20
}
}
}
}
</script>
<style lang="less" scoped>
.article-container {
> div {
min-height: 150px;
}
.header-box {
background-color: pink;
}
.content-box {
background-color: lightblue;
}
.footer-box {
background-color: lightsalmon;
}
}
</style>