一、什么是插槽
插槽(slot
)是 vue 为 组件的封装者
提供的能力。允许开发者在封装组件时,把 不确定的
、希望由用户指定的部分
定义为插槽。
可以把插槽认为是组件封装期间,为用户预留的 内容的占位符
。
二、插槽分类
1. 默认插槽
vue 官方规定:每一个 slot 插槽,都要有一个 name
名称,如果省略了 slot 的 name
属性,则有一个默认名称叫做 default
子组件中:
<template>
<div>
<h1>分类名称</h1>
<slot>插槽默认内容...</slot>
</div>
</template>
父组件中:
<template>
<div>
<my-category>
<ul>
<li
v-for="(item, index) in 10"
:key="index"
>分类{{ item }}</li>
</ul>
</my-category>
</div>
</template>
注意事项
- 没有预留插槽的内容会被丢弃(也就是说子组件中未提供插槽,而父组件在使用插槽时无效)
- 如果组件的使用者没有为插槽提供任何内容,则
slot
标签中的内容会默认展示
2. 具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个插槽 slot
指定具体的 name
名称。这种带有具体名称的插槽叫做 具名插槽
子组件中:
<template>
<div>
<!-- 头部 -->
<header>
<slot name="header"></slot>
</header>
<!-- 主体 -->
<main>
<slot name="main"></slot>
</main>
<slot></slot>
<!-- 页脚 -->
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
父组件中:
<template>
<div>
<my-layout>
<!-- 新推出的语法 -->
<template v-slot:header>页头</template>
<!-- v-slot: 的简写方式 -->
<template #main>主体</template>
<div slot="footer">页脚</div>
<template #default>
<h1>默认插槽</h1>
</template>
</my-layout>
</div>
</template>
注意事项
- 没有指定
name
名称的插槽,会有隐含的名称叫做default
v-slot:
只能使用在template
标签上,注意v-slot:
后不需要加引号#
后面加插槽名称,是v-slot:
的简写方式,类似于事件绑定(v-on
=@
),规则与v-slot:
一样slot=""
可以使用在template
或 其他标签上
3. 作用域插槽
数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。
子组件中:
<template>
<div>
<slot :title="title" :list="list"></slot>
<slot name="content" :content="content"></slot>
</div>
</template>
<script>
export default {
name: 'MyCategory',
data() {
return {
title: '美食分类',
list: [
{
id: 1,
name: '分类1'
},
{
id: 2,
name: '分类2'
},
{
id: 3,
name: '分类3'
},
],
content: '美食简介内容...'
}
}
}
</script>
<style lang="scss" scoped>
</style>
父组件中:
<template>
<div>
<my-category>
<template scope="category">
<h1>{{ category.title }}</h1>
<ul>
<li
v-for="item in category.list"
:key="item.id"
>{{ item.name }}</li>
</ul>
</template>
</my-category>
<my-category>
<template #default="category">
<h1>{{ category.title }}</h1>
<ul>
<li
v-for="item in category.list"
:key="item.id"
>{{ item.name }}</li>
</ul>
</template>
</my-category>
<!-- 可以使用更简洁的结构赋值语法 -->
<my-category>
<template scope="{list, title}">
<h1>{{ title }}</h1>
<ol>
<li
v-for="item in list"
:key="item.id"
>{{ item.name }}</li>
</ol>
</template>
</my-category>
<my-category>
<template #default="{list, title}">
<h1>{{ title }}</h1>
<ol>
<li
v-for="item in list"
:key="item.id"
>{{ item.name }}</li>
</ol>
</template>
</my-category>
<!-- 新推出的语法 -->
<my-category>
<template slot-scope="{list, title}">
<h1>{{ title }}</h1>
<ol>
<li
v-for="item in list"
:key="item.id"
>{{ item.name }}</li>
</ol>
</template>
</my-category>
<!-- 具名插槽的作用域插槽使用 -->
<my-category>
<template v-slot:content="{content}">
<div>{{content}}</div>
</template>
</my-category>
<my-category>
<template #content="{content}">
<div>{{content}}</div>
</template>
</my-category>
</div>
</template>
注意事项
- 不管哪种写法,必须使用
template
标签才行 - 可以选一种作为日常常用的写法