什么是插槽?
我们知道,在vue中,引入的子组件标签中间是不允许写内容的。为了解决这个问题,官方引入了插槽(slot)的概念。
插槽,其实就相当于占位符。它在组件中给你的HTML模板占了一个位置,让你来传入一些东西。插槽又分为匿名插槽、具名插槽以及作用域插槽。
你可能不太明白,为什么我要给子组件中传入HTML,而不直接写在子组件中呢?答案是这样的。你可以想象一个场景,你有五个页面,这五个页面中只有一个区域的内容不一样,你会怎么去写这五个页面呢?复制粘贴是一种办法,但在vue中,插槽(slot)是更好的做法。
匿名插槽
匿名插槽,我们又可以叫它单个插槽或者默认插槽。与具名插槽相对,它不需要设置name属性。(它隐藏的name属性为default。)
例子:
文件目录如下,Home组件是HelloWorld的父组件。
- 在HelloWorld中写一个匿名插槽
<template>
<div class="hello">
Helloworld组件
<div class = 'slotTxt'>
<slot></slot>
</div>
</div>
</template>
<script>
export default {
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.hello{
width:100%;
height:300px;
background:#ccc;
margin-top:50px;
.slotTxt{
width:500px;
height:200px;
margin:30px auto;
background:red;
}
}
</style>
- 在Home组件中引入子组件,并在子组件标签中写入内容
<template>
<div class="home">
我是Home父组件
<HelloWorld>
<!-- 没有插槽,这里的内容不显示 -->
<h1>我是helloworld中的插槽啊</h1>
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'home',
components: {
HelloWorld
}
}
</script>
- 效果
不难看出,HelloWorld标签中的内容(红色部分)已经显示出来了。
具名插槽
上面已经说过,插槽有一个name属性。与匿名插槽相对,加了name属性的匿名插槽就是具名插槽。
- HelloWorld组件中写入name属性分别为left和right的插槽
-
<template> <div class="hello"> Helloworld组件 <div class = 'slotLeft'> <slot name='left'></slot> </div> <div class = 'slotRight'> <slot name='right'></slot> </div> </div> </template> <script> export default { } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="less"> .hello{ width:700px; height:300px; background:#ccc; margin: 0 auto; margin-top:50px; .slotLeft{ width:300px; height:200px; float:left; background:red; } .slotRight{ width:300px; height:200px; float:right; background:pink; } } </style>
- Home组件通过在template上写v-slot:name来使用具名插槽
<template>
<div class="home">
我是Home父组件
<HelloWorld>
<template v-slot:left>
<h1>name属性为left</h1>
</template>
<template v-slot:right>
<h1>name属性为right</h1>
</template>
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'home',
components: {
HelloWorld
}
}
</script>
<style lang="less" scoped>
.home{
width:900px;
margin:0 auto;
background:yellow;
padding-bottom:100px;
}
</style>
注意 v-slot 只能添加在template标签上 (只有一种例外情况)。
- 效果
- 例外情况(被废弃的slot=‘name’)
带slot属性的具名插槽自 2.6.0 起被废弃,vue3.x被完全废弃。只有vue3之前的cli可以使用。
<template>
<div class="home">
我是Home父组件
<HelloWorld>
<h1 slot='left'>name属性为left</h1>
<h1 slot='right'>name属性为right</h1>
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'home',
components: {
HelloWorld
}
}
</script>
<style lang="less" scoped>
.home{
width:900px;
margin:0 auto;
background:yellow;
padding-bottom:100px;
}
</style>
效果同上。
- 具名插槽的小知识点
跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header。