Vue 插槽(槽位)的详细信息和使用方法
插槽:简单理解就是组件内部留一个或多个的插槽位置,可供组件传对应的模板代码进去。插槽的出现,让组件变的更加灵活。
1. 匿名插槽
父组件
// home.vue
<template>
<div class="home">
<footerComponent>
<p>我是匿名插槽</p>
</footerComponent>
</div>
</template>
<script>
import footerComponent from '@/components/footerComponent.vue'
export default {
components: {
footerComponent,
}
}
</script>
子组件
// footerComponent.vue
<template>
<div>
<h1>子组件</h1>
<slot></slot> // 替换为 <p>我是匿名插槽</p>
</div>
</template>
1.2 后备内容
有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。
父组件
// home.vue
<template>
<div class="home">
<footerComponent></footerComponent>
</div>
</template>
<script>
import footerComponent from '@/components/footerComponent.vue'
export default {
components: {
footerComponent,
}
}
</script>
子组件
// footerComponent.vue
<template>
<div>
<h1>子组件</h1>
<slot>
<p>我是后补内容</p>
</slot>
</div>
</template>
2. 具名插槽
顾名思义就是带名字的插槽,假如需要在组件内部预留多个插槽位置,就需要为插槽定义名字,指定插入的位置。
Vue 2.6.0+ 版本,使用v-slot替代slot 和 slot-scope。
注意点:
1.具名插槽的内容必须使用模板< template ></ template >包裹;
2.不指定名字的模板插入匿名插槽中,推荐使用具名插槽,方便代码追踪且直观清楚;
3.匿名插槽具有隐藏的名字"default;"
2.1 具名插槽的缩写
跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。
例如 v-slot:header 可以被重写为 #header;
然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:
// 这样会触发一个警告
<current-user #="{ user }">
{{ user.firstName }}
</current-user>
如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>
2.2 动态插槽名
动态指令参数也可以用在 v-slot 上,来定义动态的插槽名
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
父组件
// 现在 <template>元素中的所有内容都将会被传入相应的插槽。
// 任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。
<template>
<div class="home">
<footerComponent>
<template v-slot:header>
<h2>header</h2>
</template>
<template v-slot:[mybody]>
<h3>动态插槽名</h3>
</template>
<p>内容</p>
<template #footer>
<h2>footer</h2>
</template>
</footerComponent>
</div>
</template>
<script>
import footerComponent from '@/components/footerComponent.vue'
export default {
data(){
return{
mybody:'body',
}
},
components: {
footerComponent,
}
}
</script>
子组件
<template>
<div class="footerComponent">
<h1>子组件</h1>
<slot name="header"></slot>
<slot name="body"></slot>
<slot><p>我是后补内容</p></slot> // 等价于 <slot name="default"></slot>
<slot name="footer"></slot>
</div>
</template>
<style scoped lang="stylus">
.footerComponent
width 100%
height 200px
background-color pink
</style>
3. 作用域插槽
3.1 父传子
父组件
<template>
<div class="home">
<headerComponent :title="myName">
<template #header>
<h2>父组件</h2>
</template>
</headerComponent>
</div>
</template>
<script>
import headerComponent from '@/components/headerComponent.vue'
export default {
data(){
return{
myName:'我是',
}
},
components: {
headerComponent,
}
}
</script>
子组件
<template>
<div class="headerComponent">
<slot name="header"></slot>
<div class="childName">{{title}}子组件</div>
</div>
</template>
<script>
export default {
props: {
title:String
}
}
</script>
<style scoped lang="stylus">
.childName
color red
font-size 20px
</style>
父组件传递的插槽内容是由子组件编译的,插槽作用域由子组件决定。
所以如果需要动态修改插槽的内容,就需要子组件传参给父组件。
3.2 子传父
父组件传参给子组件,props接收后,插槽slot再通过绑定属性传递参数返回给父组件,不管是模板代码还是数据,控制权完全掌握在父组件手里。
第一种方式
父组件
<template>
<div class="home">
<footerComponent :myLayout="layout">
<template v-slot:header="headerSlotProps">
<h2>{{headerSlotProps.header}}</h2>
</template>
<template v-slot="slotProps">
<p>{{slotProps.content}}</p>
</template>
<template #footer="slotProps">
<h2>{{slotProps.footer}}</h2>
</template>
</footerComponent>
</div>
</template>
<script>
import footerComponent from '@/components/footerComponent.vue'
export default {
data(){
return{
layout:{
header:'头部',
content:'内容',
footer:'脚部'
},
}
},
components: {
footerComponent
}
}
</script>
子组件
<template>
<div class="footerComponent">
<h1>子组件</h1>
<slot name="header" :header="myLayout.header"></slot>
<slot :content="myLayout.content"><p>我是后补内容</p></slot>
<slot name="footer" :footer="myLayout.footer"></slot>
</div>
</template>
<script>
export default {
props: {
myLayout:Object
}
}
</script>
<style scoped lang="stylus">
.footerComponent
width 100%
height 250px
background-color pink
</style>
第二种方式
子组件通过属性 <slot :自定义属性名 = '值'></slot>,将自己内部的原始类型给到父组件;
父组件 <template slote-scope='自定义接收'></template>;
子组件 slot 除了要占个位置还要传递参数,父组件 slote-scope 负责接收参数;
父组件
<template>
<div class="home">
<childComponent :list="provinces">
<template slot-scope="slotProps">
<h4 v-for="city in slotProps.cities" :key="city.id" >
城市: {{city.name}}
</h4>
</template>
</childComponent>
</div>
</template>
<script>
import childComponent from './itemComponent.vue'
export default {
data(){
return{
provinces:[
{
id:1,
name:'江苏',
cities:[
{id:11,name:'南京'},
{id:12,name:'苏州'}
]
},{
id:2,
name:'湖北',
cities:[
{id:21,name:'武汉'},
{id:22,name:'鄂州'}
]
},
]
}
},
components: {
childComponent
}
}
</script>
-------------------------第一种方式实现,其余部分不变-------------------------------
<template>
<div class="home">
<childComponent :list="provinces">
<template v-slot="slotProps">
<h4 v-for="city in slotProps.cities" :key="city.id" >
城市: {{city.name}}
</h4>
</template>
</childComponent>
</div>
</template>
子组件
<template>
<div class="footerComponent">
<div v-for="item in list" :key="item.id">
<h2>省份:{{item.name}}</h2>
<slot :cities="item.cities"></slot>
</div>
</div>
</template>
<script>
export default {
props: {
list:{
type: Array,
default: function(){
return []
}
}
}
}
</script>
参考文章(侵删)
上一篇: 彻底弄清*的位置,图文并茂
下一篇: Vue 中的神奇插槽
推荐阅读
-
详细讲解 Vue 插槽的使用方法和案例演示,阅读后完全理解
-
分析 Vue 中插槽槽位的使用
-
Vue 插槽(槽位)的详细信息和使用方法
-
Vue 中插槽槽的用法和应用场景
-
Vue 插槽(槽位)的详细信息和使用方法
-
其主要作用是实现组件的重用和封装,使组件更具灵活性和可定制性。具体来说,可以在组件内部注入插槽来实现动态渲染,同时还能保留组件的固有结构和风格。槽的优点是使组件更加灵活,通过槽可以传递不同类型的数据,实现不同的表达形式。缺点是使用插槽会导致代码可读性差,同时也会增加实现成本。 本文主要介绍 Vue3 插槽 slot 的使用。 I.默认槽 示例代码:
-
学习 vue 中的插槽槽位和 $slots 集的使用
-
了解 Vue3 中插槽槽使用方法的文章!
-
vue 中的插槽槽位和槽位输出值
-
Vue 中的插槽用法:默认槽、命名槽和作用域槽