vue中插槽的定义:
指的是子组件中提供给父组件使用的一个占位符;
用标签<slot></slot>
表示,父组件可以在这个占位符中填充任何模板代码,比如HTML、组件等,填充的内容会替换掉子组件的标签(替换占位符)。
在Vue中,有三种类型的插槽可用于组件间的内容分发:
默认插槽,具名插槽,作用域插槽
插槽的作用:
让父组件可以向子组件指定位置插入dom结构, 组件间通讯的一种方式,适用于父组件=>子组件;
1、默认插槽(Default Slot) - 匿名插槽
默认插槽是最简单的一种插槽,就是通过替换占位符达到在父组件中更改子组件中内容的效果。默认插槽(匿名插槽)也是最常见的一种插槽类型。当组件没有具名插槽时,所有没有被包裹在具名插槽中的内容都会被放置在匿名插槽中。在组件模板中使用<slot></slot>
标签来表示匿名插槽。
1.没有为插槽指定名称
2.通过slot标签可以添加匿名插槽
3.在使用组件的时候,组件中的内容会填充到所有匿名插槽的位置(虽多个匿名插槽不会报错, 但在开发中推荐只有一个匿名插槽)
4.匿名插槽可设置默认内容,如果没有传入内容就使用默认内容,如果传入了,就会进行覆盖
5.多个插槽混用时,v-slot不能省略default,需要严格使用template语法
--------------------------没有默认值------------------------------
// 在子组件中放置一个占位符(slot):
<template>
<div>
<div>你是谁?</div>
<slot></slot>
</div>
</template>
export default {
name: 'ChildComp',
}
// 父组件中引用这个子组件,并给这个占位符(slot)填充内容:
<template>
<div>
<div>请问?</div>
<ChildComp>
<div>我是Alex</div>
</ChildComp>
</div>
</template>
// 页面实际展现内容:【请问? 你是谁?我是Alex】
--------------------------设置默认值------------------------------
// 在子组件中放置一个占位符(slot):
<template>
<div>
<div>你是谁?</div>
<slot>如果没有设置插入的标签,我就会出现</slot>
</div>
</template>
export default {
name: 'ChildComp',
}
// 父组件中引用这个子组件,并给这个占位符(slot)填充内容:
<template>
<div>
<div>请问?</div>
<ChildComp></ChildComp>
</div>
</template>
// 页面实际展现内容:【请问? 你是谁?如果没有设置插入的标签,我就会出现】
2、具名插槽(Named Slot)
具名插槽允许你在组件中定义多个插槽,并为它们命名。
父组件就可以根据插槽的名称将内容分发到相应的插槽中。
在组件模板中使用标签的<slot name="名称"></slot>
的name属性来表示具名插槽。
1.为slot设置名字的插槽就称为具名插槽
2.一个封装组件中可以有多个具名插槽
3.使用:通过template标签指定内容所放置的插槽名称
4.使用简写:`v-slot:名字` 或者 `#名字`
Vue2.6.0, 具名插槽 和 作用域插槽 引入了一个新的统一的语法(即v-slot指令), 它取代了 slot 和 slot-scope
在Vue2.6之前, 我们通过slot属性告诉Vue当前内容填充到哪一个具名插槽
从Vue2.6开始, 我们通过v-slot指令告诉Vue当前内容填充到哪一个具名插槽
5.v-slot属性只可以在template标签使用
// 子组件
<template>
<div>
<slot name="header"></slot>
<slot name="content"></slot>
<slot name="footer"></slot>
</div>
</template>
export default {
name: 'ChildComp',
}
// 父组件使用具名插槽分发内容:
<template>
<ChildComp>
<template v-slot:header>
<div>我是header</div>
</template>
// 等价于
/*
<template #header>
<div>我是header</div>
</template>
*/
<template v-slot:content>
<div>我是content</div>
</template>
<template v-slot:footer>
<div>我是footer</div>
</template>
</ChildComp>
</template>
3、作用域插槽(Scoped Slot)
作用域插槽允许子组件将数据传递给父组件,以便父组件可以在插槽中使用。 通过在子组件中使用标签的属性和具名插槽结合,可以将子组件的数据传递给父组件。 即:插槽绑定了props数据(除了name),这种带有props数据的插槽叫做"作用域插槽"
1.v-slot属性只可以在template标签使用,
但只有默认值时,可以直接省略template, v-slot直接绑定到父组件
Vue2.6.0, 具名插槽 和 作用域插槽 引入了一个新的统一的语法(即v-slot指令), 它取代了 slot 和 slot-scope
-----------------------匿名插槽---------------------------
// 子组件模板:
<template>
<div>
<slot :data="info"></slot>
// 等价于
// <slot v-bind:data="info"></slot>
</div>
</template>
<script>
export default {
name: 'ChildComp',
data() {
return {
info: 'child',
};
}
};
</script>
// 父组件使用作用域插槽获取子组件数据:
<template>
<ChildComp>
<template v-slot:default="slotProps">
<p>{{ slotProps.data }}</p>
</template>
// 等价于
/*
<template v-slot="slotProps">
<p>{{ slotProps.data }}</p>
</template>
*/
// 等价于
/*
<template #default="slotProps">
<p>{{ slotProps.data }}</p>
</template>
*/
</ChildComp>
// 当提供的内容只有默认插槽时,可以直接在组件上使用v-slot:default="slotProps",甚至直接v-slot="slotProps"
即:下面两种方式与上面一种是等价的
<ChildComp v-slot:default="slotPorp">
<p>{{ slotProps.data }}</p>
</ChildComp>
<ChildComp v-slot="slotPorp">
<p>{{ slotProps.data }}</p>
</ChildComp>
</template>
-------------------------具名插槽--------------------------
// 子组件模板:
<template>
<div>
<slot
name="data"
:gender="gender"
:age="age"
:username="username"
></slot>
</div>
</template>
<script>
export default {
name: 'ChildComp',
data() {
return {
gender: 'male',
age: 18,
username: 'alex'
};
}
};
</script>
// 父组件使用作用域插槽获取子组件数据:
// 因为传递过来的数据是一个对象,所以可以用解构的方式来获取数据
// 也支持重命名v-slot="{age: newAge}" 和 定义默认值v-slot="{age = 20}"
<template>
<ChildComp>
<template v-slot:data="{gender,age,username}">
<p>{{ username }}</p>
<p>{{ age }}</p>
<p>{{ gender }}</p>
</template>
</ChildComp>
</template>
支持 动态插槽名
<ChildComp>
<template v-slot:[dynamicSlotName]>
</template>
<!-- 等价于 -->
<template #[dynamicSlotName]>
</template>
</ChildComp>
<script>
export default {
data() {
return {
dynamicSlotName: "header"
};
}
};
</script>