开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第27天,点击查看活动详情
插槽
1. 什么是插槽
插槽通俗地讲就是在封装组件的时候,对不确定部分的内容的一种占位。这个展位用slot标签表示,然后在具体使用过程中根据实际内容将其放在这个slot标签的位置。
<template>
<div class="slot-wrapper">
<div class="titler-wrapper">{{title}}</div>
<slot></slot>
</div>
</template>
注意: 只有在组件中使用了slot标签占位之后,组件标签之间的内容才能被渲染,否则是会被抛弃的
2. 插槽的编译作用域
插槽里面的内容是父组件根据自身的实际情况来定义的,是属于父组件作用域的,而子组件是属于子组件作用域的。它们之间是不能直接访问的。 插槽
<template>
<div class="slot-wrapper">
<div class="titler-wrapper">{{title}}</div>
<slot></slot>
</div>
</template>
父组件
<template>
<div class="hello">
<testSlot title="电影分类">
<span>{{title}}</span>
</testSlot>
</div>
</template>
此时这样是获取不到title的, 页面会报错。
3. 组件的分类
我们在使用插槽的时候,主要可以分为三类:默认插槽,具名插槽,作用域插槽
默认插槽
默认插槽很简单,就是子组件中写了一个slot标签,那么在父组件中子组件中间的所有内容都是默认插槽的内容。
<template>
<div class="slot-wrapper">
<div class="titler-wrapper">{{title}}</div>
<slot>好听的歌曲</slot>
</div>
</template>
<script>
export default {
name: 'testSlot',
props: ['title'],
data() {
return {
}
}
}
</script>
<style lang="css" scoped>
.slot-wrapper {
width: 200px;
height: 500px;
border: 1px solid #999;
border-radius: 4px;
}
.titler-wrapper {
width: 100%;
height: 40px;
line-height: 40px;
background-color: aquamarine;
text-align: center;
}
</style>
像上面这种,slot标签上没有任何属性,那么这个插槽就是默认插槽,组件中只能有一个默认插槽
1. 后备内容
<template>
<div class="hello">
<testSlot :title="title">
</testSlot>
</div>
</template>
<script>
import testSlot from './testSlot.vue';
export default {
name: 'HelloWorld',
components: {
testSlot
},
data() {
return {
title: '电影分类'
}
},
methods: {
}
}
</script>
<style scoped>
</style>
如果父组件不传插槽的内容,那么就默认展示后备内容
2. 展示配置的插槽内容
<template>
<div class="hello">
<testSlot :title="title">
<div>经典歌曲</div>
<div>流行歌曲</div>
<div>排行歌曲</div>
<div>热门歌曲</div>
</testSlot>
</div>
</template>
<script>
import testSlot from './testSlot.vue';
export default {
name: 'HelloWorld',
components: {
testSlot
},
data() {
return {
title: '电影分类'
}
},
methods: {
}
}
</script>
<style scoped>
</style>
具名插槽
当组件中需要根据结构区分很多插槽时,需要给每个插槽命一个名,这时就有了具名插槽
<template>
<div class="slot-wrapper">
<div class="titler-wrapper">{{title}}</div>
<slot name="center"></slot>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: 'testSlot',
props: ['title'],
data() {
return {
}
}
}
</script>
<style lang="css" scoped>
.slot-wrapper {
width: 200px;
height: 500px;
border: 1px solid #999;
border-radius: 4px;
}
.titler-wrapper {
width: 100%;
height: 40px;
line-height: 40px;
background-color: aquamarine;
text-align: center;
}
</style>
废弃写法
<template>
<div class="hello">
<testSlot :title="title">
<div slot="center">
<div>经典歌曲</div>
<div>流行歌曲</div>
<div>排行歌曲</div>
<div>热门歌曲</div>
</div>
<div slot="footer">更多好听音乐请关注公众号</div>
</testSlot>
</div>
</template>
<script>
import testSlot from './testSlot.vue';
export default {
name: 'HelloWorld',
components: {
testSlot
},
data() {
return {
title: '电影分类'
}
},
methods: {
}
}
</script>
<style scoped>
</style>
最新写法
<template>
<div class="hello">
<testSlot :title="title">
<template v-slot:center>
<div>经典歌曲</div>
<div>流行歌曲</div>
<div>排行歌曲</div>
<div>热门歌曲</div>
</template>
<template v-slot:footer>更多好听音乐请关注公众号</template>
</testSlot>
</div>
</template>
<script>
import testSlot from './testSlot.vue';
export default {
name: 'HelloWorld',
components: {
testSlot
},
data() {
return {
title: '电影分类'
}
},
methods: {
}
}
</script>
<style scoped>
</style>
简写形式
<template>
<div class="hello">
<testSlot :title="title">
<template #center>
<div>经典歌曲</div>
<div>流行歌曲</div>
<div>排行歌曲</div>
<div>热门歌曲</div>
</template>
<template #footer>更多好听音乐请关注公众号</template>
</testSlot>
</div>
</template>
效果如下:
注意 v-slot 只能添加在 <template> 上
作用域插槽
前面我们介绍过插槽中的作用域,父级作用域和子级作用域是不能互相直接访问的。如果要访问的话,那就只能使用作用域插槽了。
1. 基础用法
slot中要将内容绑定上
<template>
<div class="slot-wrapper">
<div class="titler-wrapper">{{title}}</div>
<slot :user="user">{{user.lastName}}</slot>
</div>
</template>
<script>
export default {
name: 'testSlot',
props: ['title'],
data() {
return {
user: {
firstName: '张',
lastName: '阿强'
}
}
}
}
</script>
<style lang="css" scoped>
.slot-wrapper {
width: 200px;
height: 500px;
border: 1px solid #999;
border-radius: 4px;
}
.titler-wrapper {
width: 100%;
height: 40px;
line-height: 40px;
background-color: aquamarine;
text-align: center;
}
</style>
插槽中使用v-slot:插槽名=“变量名进行获取”,如果是默认插槽可以简写为v-slot="slotProps"
<template>
<div class="hello">
<testSlot :title="title">
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</testSlot>
</div>
</template>
<script>
import testSlot from './testSlot.vue';
export default {
name: 'HelloWorld',
components: {
testSlot
},
data() {
return {
title: '电影分类'
}
},
methods: {
}
}
</script>
<style scoped>
</style>
效果如下:
2. 解构插槽
如果插槽中的作用域变量是个对象,还可以进行解构。
<template>
<div class="hello">
<testSlot :title="title">
<template v-slot:default="{ user }">
{{ user.firstName }}
</template>
</testSlot>
</div>
</template>
也可以赋值
<template>
<div class="hello">
<testSlot :title="title">
<template v-slot:default="{ user = { firstName: '李' } }">
{{ user.firstName }}
</template>
</testSlot>
</div>
</template>
这种解构和es6中的解构是一样的