Vue3学习笔记之插槽

目录

前言

一、基础

(一) 默认插槽

(二) 具名插槽

(三) 作用域插槽

(四) 动态插槽

二、实战案例


前言

插槽(Slots)?

插槽可以实现父组件自定义内容传递给子组件展示,相当于一块画板,画板就是我们的子组件,我们在上面定义好布局和固定内容,然后将需要变化的部分空出来(挖坑),然后别人就可以根据需要在这个坑位上填充内容

插槽功能可以让我们实现组件多样化减少重复代码,对于封装组件也是提供了巨大的帮助

一、基础

(一) 默认插槽

插槽的实现方式很简单,子组件需要在填充内容的部分写上标签slot即可,然后父组件在引入子组件标签写入内容,填入的内容就会展示到子组件中

子组件

<div class="box">
  <header>头部</header>
  <main>
    <!-- 插槽 -->
    <slot></slot>
  </main>
  <footer>尾部</footer>
</div>

父组件

<div>
    <Child>父组件定义的内容</Child>
</div>

在子组件中定义了头部和尾部,而中间的内容区域由父组件填充

(二) 具名插槽

当一个组件需要多个插槽或需要父组件内容插入到位置上时就需要到具名插槽

子组件

<div class="box">
  <header>头部</header>
  <main>
    <!-- 插槽-1 -->
    <slot name="main"></slot>
  </main>
  <footer>
    <!-- 插槽-2 -->
    <slot name="footer"></slot>
  </footer>
</div>

父组件

<Child>
  <template #main>
    <button>hello</button>
  </template>
  <template #footer>
    <p>哈哈哈哈哈</p>
  </template>
</Child>

效果

(三) 作用域插槽

子组件可以通过动态绑定的方式,将子组件的值通过插槽传递给父组件

子组件

<div class="box">
  <header>头部</header>
  <main>
    <!-- 插槽 -->
    <slot name="main" :title="'Vue3'"></slot>
  </main>
</div>

父组件

<Child>
  <template #main="{ title }">
    <p>我是子组件传递的值:{{ title }}</p>
  </template>
</Child>

效果

(四) 动态插槽

动态插槽:可以根据名称去动态匹配插槽位置

子组件

<div class="box">
  <header>
    <!-- 插槽 -->
    <slot name="header"></slot>
  </header>
  <main>
    <!-- 插槽 -->
    <slot name="main"></slot>
  </main>
  <footer>
    <!-- 插槽 -->
    <slot name="footer"></slot>
  </footer>
</div>

父组件

<script setup lang="ts">
import Child from "./components/Child.vue";
const slotName = ref("main");
</script>

<template>
  <div>
    <Child>
      <template #[slotName]> 鸡你太美 </template>
    </Child>
  </div>
</template>

二、实战案例

结合element-plus封装一个管理后台系统的数据表格,后台管理系统中,常见的就是数据表格的展示,一般模块就需要一个表格进行展示,但是表格有些代码是重复性的,如果每个模块都要写一份新的表格代码,那就发生耗费时间代码重复性高可维护性差等问题,那此时就可以将表格封装成组件,并加上插槽扩大表格的可拓展性

Table封装组件

<script setup lang="ts">
interface Props {
  tableColumn: any;
  tableData: any;
}

defineProps<Props>();
</script>

<template>
  <el-table :data="tableData" stripe style="width: 100%">
    <el-table-column
      v-for="column in tableColumn"
      :key="column.prop"
      :prop="column.prop"
      :label="column.label"
    />
    <el-table-column fixed="right" label="操作">
      <template #default="scope">
        <slot name="left"></slot>
        <el-button link type="primary" size="small"> 添加 </el-button>
        <el-button link type="danger" size="small">删除</el-button>
        <slot name="right" :row="scope.row"></slot>
      </template>
    </el-table-column>
  </el-table>
</template>

父组件

<script setup lang="ts">
import CyTable from "./components/CyTable.vue";

const tableColumn = [
  {
    label: "出生日期",
    prop: "date",
  },
  {
    label: "姓名",
    prop: "name",
  },
  {
    label: "住址",
    prop: "address",
  },
];

const tableData = [
  {
    date: "2016-05-03",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-02",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-04",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
  {
    date: "2016-05-01",
    name: "Tom",
    address: "No. 189, Grove St, Los Angeles",
  },
];
</script>

<template>
  <div class="box">
    <header>头部</header>
    <main>
      <CyTable :tableColumn="tableColumn" :tableData="tableData">
        <template #right="{ row }">
          <p>获取</p>
          {{ row }}
        </template>
      </CyTable>
    </main>
    <footer>尾部</footer>
  </div>
</template>

<style scoped>
.box {
  width: 100vw;
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
header {
  text-align: center;
  width: 100%;
  height: 100px;
}
main {
  box-sizing: border-box;
  padding: 50px;
  margin: 20px;
  width: 80%;
  flex: 1;
  background-color: skyblue;
}
footer {
  text-align: center;
  width: 100%;
  height: 200px;
}
</style>

实现效果

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值