一、插槽的应用场景
在某些场景中,封装组件,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。由此出现了插槽
二、插槽的内容与出口
1、出口
封装的组件代码如下图所示:
<template>
<el-button type="primary">
<slot></slot> //出口
</el-button>
</template>
2、 内容
页面对封装组件的应用
<template>
<my-button>
<!--内容-->
按钮
</my-button>
</template>
<script setup>
import myButton from "./components/myButton.vue";
</script>
注意:为插槽默认指定内容,代码如下图所示
封装组件的代码:
<template>
<el-button type="primary">
<slot>
<!-- 默认内容 -->
提交
</slot>
</el-button>
</template>
应用组件代码:
<template>
<!-- 默认内容 -->
<my-button></my-button>
</template>
<script setup>
import myButton from "./components/myButton.vue";
</script>
运行结果如下图所示:
图一 插槽赋值
图二 插槽默认值
三、插槽的分类
1、一般插槽
只有插槽的出口以及内容(赋值内容或者默认内容),无其他信息,用法如上
2、具名插槽
通俗的说,就是有名字的插槽。有时在一个组件中包含多个插槽出口是很有用的,
<slot>
元素可以有一个特殊的 attributename
,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容,这类带name
的插槽被称为具名插槽 (named slots)。没有提供name
的<slot>
出口会隐式地命名为“default”。
要为具名插槽传入内容,我们需要使用一个含 v-slot
指令的 <template>
元素,并将目标插槽的名字传给该指令,具体内容如下:
封装组件:
<template>
<div class="container">
<div class="title">
<div>
<!--这里的name 是具名插槽的名称-->
<slot name="title"></slot>
</div>
<div class="right">
<!--这里的name 是具名插槽的名称-->
<slot name="option"></slot>
</div>
</div>
<div class="content">
<!--这里的插槽没有name,则默认为default-->
<slot></slot>
</div>
</div>
</template>
<style scoped>
.container {
border-radius: 4px;
border: 1px solid #ebeef5;
background-color: #fff;
color: #303133;
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
}
.title {
display: flex;
justify-content: space-between;
font-size: 20px;
font-weight: 500;
padding: 18px 20px;
border-bottom: 1px solid #ebeef5;
box-sizing: border-box;
}
.content {
padding: 20px;
}
</style>
应用组件:
<template>
<my-card class="box-card">
<!-- title 插槽的内容放这里 -->
<template v-slot:title>标题</template>
<!-- option 插槽的内容放这里 -->
<template v-slot:option>
<el-button type="primary" link>操作</el-button>
</template>
<!-- 默认插槽的内容放这里 -->
卡片内容是哈哈哈哈
</my-card>
</template>
<script setup>
import myCard from "./components/myCard.vue";
</script>
<style scoped>
.box-card {
width: 480px;
}
</style>
运行效果
图三 具名插槽的应用
3、作用域插槽
上边的两种插槽有一个共同点:插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的;无法访问子组件的数据,Vue 模板中的表达式只能访问其定义时所处的作用域,这和 JavaScript 的词法作用域规则是一致的,即:
父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。
由此,产生了作用域插槽。
(1)封装组件代码如下:
<template>
<div class="list-container">
<div class="list-item" v-for="(item, i) in data" :key="i">
<div class="first">
<div>姓名:{{ item.name }}</div>
<!-- 默认插槽的 name 为defalut,message 是作用域插槽传递的参数 -->
<slot :message="item.name"></slot>
</div>
</div>
</div>
</template>
<script setup>
import {} from "vue";
defineProps(["data"]);
</script>
<style scoped>
.list-container {
}
.list-item {
border: 1px solid #ccc;
margin-bottom: 10px;
padding: 10px;
}
.first {
display: flex;
justify-content: space-between;
}
</style>
(2)应用组件代码如下:
<template>
<my-list :data="tableArr">
<!-- default 是插槽的名称,message 是组件传的参数 -->
<template #default="{ message }">
<el-button type="primary" @click="handleClick(message)">详情</el-button>
</template>
</my-list>
</template>
<script setup>
import { ref } from "vue";
import myList from "./components/myList.vue";
const tableArr = ref([
{
date: "2016-05-02",
name: "张峰",
province: "江苏省",
city: "南京市",
address: "南京市江宁区将军大道",
zip: 200333,
},
{
date: "2016-05-04",
name: "吴丹",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1517 弄",
zip: 200333,
},
{
date: "2016-05-01",
name: "林天",
province: "江苏省",
city: "南京市",
address: "南京市雨花台区软件大道",
zip: 200333,
},
]);
const handleClick = (obj) => {
console.log("点击:", obj);
};
</script>
(3)运行效果如下:
图四 作用域插槽默认展示
文章来源:https://www.toymoban.com/news/detail-763118.html
图五 作用域插槽传递姓名参数 文章来源地址https://www.toymoban.com/news/detail-763118.html
到了这里,关于vue3 插槽详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!