目录
什么是插槽?
在 UniApp 中,插槽(Slot)是一种允许父组件向子组件特定位置插入HTML内容的方式。这种方式使得组件更加灵活,可以被复用在多种场景下,同时让父组件能够控制子组件的部分呈现内容。
基本概念
默认插槽:当没有特别指定插槽名称时,默认插槽就是指没有名字的插槽,可以在子组件中直接使用
<slot></slot>
标签来定义一个默认插槽的位置。命名插槽:如果需要在子组件中定义多个插槽,可以通过
<slot name="slotName"></slot>
来定义具有特定名称的插槽。父组件则需要使用<template v-slot:slotName>...</template>
或者更简洁的<template #slotName>...</template>
来填充这些具名插槽。作用域插槽:有时候父组件需要访问子组件的数据或属性,这时候就需要使用作用域插槽。子组件需要在
<slot>
标签中声明需要传递给父组件的数据,如<slot name="slotName" :items="items"></slot>
。父组件在使用这个插槽时,可以通过v-slot:slotName="{ items }"
来接收这些数据,并根据这些数据进行渲染。
默认插槽
子插槽:
<slot>
元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。<template> <view class="all"> <view class="header"> 头部 </view> <view class="main"> <slot></slot> </view> <view class="footer"> 底部 </view> </view> </template> <script setup> </script> <style lang="scss" scoped> .header { position: sticky; top: 0; background-color: green; height: 100px; z-index: 1; // 确保头部始终在最上层 } .main { height: 100px; } .footer { background-color: rosybrown; height: 120px; } </style>
父组件:可以通过调用直接在组件内部编写代码,只适合一个插槽的场景
<template> <bdqn-header> 661 </bdqn-header> </template> <script setup> </script> <style scoped lang="scss"> </style>
命名插槽
子插槽:定义了多个插槽,会导致什么问题呢???
<template> <view class="all"> <view class="header"> <slot></slot> </view> <view class="main"> <slot></slot> </view> <view class="footer"> <slot></slot> </view> </view> </template>
当出现多个插槽的时候会导致插入的时候,会在每个插槽都插入相同的数据
<template> <bdqn-header> 661 </bdqn-header> </template>
调用插槽后会导致多个相同结构,使一个结构体重复出现多次
那么如何解决呢? 这个时候就可以用到命名插槽,在插槽标签slot中添加name属性,在调用的时候使用v-slot:名称来指定插槽插入,这样就可以避免一次性调用多个插槽,也可以简写为 #名称
<template> <view class="all"> <view class="header"> <slot name="header"></slot> </view> <view class="main"> <slot name="main"></slot> </view> <view class="footer"> <slot name="footerK"></slot> </view> </view> </template>
调用子插槽的时候 通过添加 v-slot:名称 来指定插槽的位置
<template> <bdqn-header> <template v-slot:header> 头部 </template> <template v-slot:main> 主体 </template> <template v-slot:footerK> 尾部 </template> </bdqn-header> </template> <template> <bdqn-header> <template #header> 头部 </template> <template #main> 主体 </template> <template #footerK> 尾部 </template> </bdqn-header> </template>
效果图:可以看见这样子就可以实现分别给多个插槽编写不同的实现代码
作用域插槽
作用域插槽就是可以让子插槽和父组件相互传值,相互访问
场景一:子插槽向父组件传递一个字符串
子插槽:通过name指定插槽的名称,定义一个text的变量并赋值 ( 语法 变量=值 )
<template> <view class="all"> <view class="header"> <slot name="header" text="头部:我是一个字符串"></slot> </view> <view class="main"> <view> <!-- 定义一个作用域插槽,并传递数据 --> <slot name="main" text="局部:我是一个字符串"></slot> </view> </view> <view class="footer"> 底部 </view> </view> </template>
父组件:
- 通过
v-slot:header="{ text }"
定义了一个名为header
的作用域插槽。text
是从子组件传递过来的数据。- 在模板中通过
{{ text }}
显示传递过来的文本。<template> <!-- 使用自定义组件 bdqn-header,并为其定义两个作用域插槽:header 和 main --> <bdqn-header> <!-- 定义 header 作用域插槽,并访问子组件传递的 text 数据 --> <template v-slot:header="{ text }"> <view>{{ text }}</view> </template> <!-- 定义 main 作用域插槽,并访问子组件传递的 text 数据 --> <template v-slot:main="{ text }"> <view>{{ text }}</view> </template> </bdqn-header> </template>
运行效果
场景二:子插槽向父组件传递对象
子插槽:向父组件传递了一个items对象( 语法 :名称="传递的对象" )
<template> <view class="all"> <!-- 头部区域 --> <view class="header"> <!-- 使用插槽传递头部内容,提供默认文本 --> <slot name="header" text="头部:我是一个字符串"></slot> </view> <!-- 主要内容区域 --> <view class="main"> <!-- 包裹一个view以便于统一管理插槽内容 --> <slot name="main" :items="items"></slot> </view> <!-- 底部区域,直接输出底部内容 --> <view class="footer"> 底部 </view> </view> </template> <script setup> // 导入Vue的响应式函数ref import { ref } from 'vue'; // 定义一个响应式的items数组,包含姓名和年龄信息 var items = ref([{ name: '张三', age: 18 }, { name: '李四', age: 19 }, { name: '王五', age: 25 }]) </script> <style lang="scss" scoped> .header { position: sticky; top: 0; background-color: green; height: 100px; z-index: 1; // 确保头部始终在最上层 } .main { height: 100px; } .footer { background-color: rosybrown; height: 120px; } </style>
父组件: 通过插槽接收子插槽传递的对象 ( 语法 #main="{items}" )
- 通过
#main
插槽展示列表项。- #main表示插槽指定的名称(name名称)
- "{items}" 表示传递的对象,使用{}包裹
<template> <!-- 使用自定义组件bdqn-header来构建页面布局 --> <bdqn-header> <!-- 通过header插槽自定义头部内容 --> <template v-slot:header="{ text }"> <view>{{ text }}</view> </template> <!-- 通过main插槽展示主体内容,通常用于列表展示 --> <template #main="{items}"> <view v-for="item in items"> {{item.name}} {{item.age}} </view> </template> </bdqn-header> </template>
执行的结果