组件可以接收任意类型的JS值作为props,但我们想要为子组件传递一些模板片段,并在子组件中进行渲染时,此时可以采用插槽slot来实现
简单来说,插槽时组件内留一个或多个插槽的位置,供组件传递对应的模板代码(传递任意HTML的结构),插槽的存在使得组件变的更为灵活
Slot与Props的比较
使用props的方式传递以下的模版片段:
<div>
<h3>父级标题</h3>
<p>父级内容</p>
</div>
Props的方式
// Parent.vue
<template>
<h2>父组件</h2>
<Child :title="父级标题" :content="父级内容"/>
</template>
<script>
import Child from "./Child.vue";
export default {
data(){
return{
}
},
components:{
Child
}
}
</script>
// Child.vue
<template>
<h2>子组件</h2>
<div>
<h3>{{title}}</h3>
<p>{{content}}</p>
</div>
</template>
<script>
export default {
data(){
return{
}
},
props:["title","content"]
}
</script>
使用插槽slot的方式
// Parent.vue
<template>
<h2>父组件</h2>
<Child>
<div>
<h3>父级标题</h3>
<p>父级内容</p>
</div>
</Child>
</template>
<script>
import Child from "./Child.vue";
export default {
data(){
return{
}
},
components:{
Child
}
}
</script>
// Child.vue
<template>
<h2>子组件</h2>
<slot></slot>
</template>
<script>
export default {
data(){
return{
}
}
}
</script>
通过props和slot的比较,可看出当模块结果过于复杂时,插槽slot是更优选
插槽默认内容
当父级未提供任何内容给子级的情况下,子级可为插槽指定默认内容
// Parent.vue 中的 template块
<template>
<h2>父级</h2>
<Child />
</template>
// Child.vue 中 的template块
<template>
<h2>子级</h2>
<slot>默认内容</slot>
</template>
具名插槽
具名插槽:即带名字的插槽,当需要在组件内预留多个插槽的位置时,则需为插槽定义名字,指定插入的位置
注:
为具名插槽传入内容时:
对于父级组件,需要使用一个含 v-slot 指令的 <template>元素,并将目标插槽的名字传给该指令;(其中,v-slot可将其简写为# (v-bind可简写为:) )
对于子级组件,<slot>元素需要一个特殊的属性 name ,用于为各个插槽分配唯一的ID,以确定每一处要渲染的内容
// Parent.vue
<template>
<Child>
<template v-slot:header>
<p>Header</p>
</template>
<template #main>
<p>Main</p>
</template>
</Child>
</template>
v-slot:header 与 #header 是等价的
//Child.vue
<template>
<slot name="header"></slot>
<slot name="main"></slot>
</template>
具名插槽传数据(子父组件数据交互的实现)
通过插槽的方式,将子组件中的内容进行显示
// Parent.vue
<template>
<Child>
<template v-slot:header="slotProps">
<p>{{ currentMsg }}--{{ slotProps.content }}</p>
</template>
<template #main="slotProps">
<p>{{ slotProps.content1}}</p>
</template>
</Child>
</template>
<script>
import Child from "./Child.vue";
export default {
data(){
return{
currentMsg:"父级组件的内容"
}
},
components:{
Child
}
}
</script>
// Child.vue
<template>
<slot name="header" :content="contentMsg"></slot>
<slot name="main" :content1="contentMsg1"></slot>
</template>
<script>
export default {
data(){
return{
contentMsg:"子级组件的内容",
contentMsg1:"子级组件的内容1",
}
}
}
</script>