Vue3中slot插槽的使用

Vue3中slot插槽的使用

插槽在什么时候使用呢?

vue中 我们要使用子组件的时候需要给子组件传一些特定的模板,这个时候你就需要用插槽。 插槽在一些封装组件中有很大的用处,插槽有匿名插槽、后备内容、具名插槽、作用域插槽,下面我们就通过一些例子来学习一下

插槽的基本使用

1 定义一个子组件child.vue

<template>
  <div class="child-con">
    <p>我是子组件2</p>
    <slot></slot>  <!--插槽的出口 -->
  </div>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>

2.定义一个父组件,然后父组件引入子组件

<template>
  <div class="test-con">
    <p>我是父组件1</p>
    <child></child>
  </div>
</template>
<script setup lang="ts">
import Child from "./components/child.vue";
</script>
<style scoped>
</style>

此时页面变成了

image-20231009150712367

我们可能想要为子组件传递一些特别模板片段

<template>
  <div class="test-con">
    <p>我是父组件1</p>
    <child>
      <div>向子组件传递一些特别模板片段</div>
    </child>
  </div>
</template>
<script setup lang="ts">
import Child from "./components/child.vue";
</script>

此时页面变成了

image-20231009151037198

我们发现在标签之间插入的内容被渲染出来了,前面我们说 slot 就是挖了一个槽出来,可以放置东西,这里我们在父组件中添加的 div 便就是我们要添加的东西,子组件中 slot 标签被替换为了我们插入的 div 元素。这就是插槽的最基本使用。

定义组件插槽设置默认内容

1.修改一下 child.vue 代码:

<template>
  <div class="child-con">
    <p>我是子组件2</p>
    <slot>
      <p>我是默认内容</p>
    </slot>  <!--插槽的出口 -->
  </div>
</template>

此时页面

image-20231009152204969

2.那么我们我们往 child 组件传入一点内容会是什么效果呢?

<template>
  <div class="test-con">
    <p>我是父组件1</p>
    <child>
      <div>{{ message }}</div>
    </child>
  </div>
</template>
<script setup lang="ts">
import Child from "./components/child.vue";
import { ref } from "vue";
const message = ref("这是父组件向子组件插入的message");
</script>

此时页面变成了

image-20231009152435166

有上面的例子看出slot 标签内的内容就是默认内容,也就是当父组件没有传递给子组件内容时,子组件就会默认渲染 slot 内部的内容,但是当父组件有传递给子组件内容时,就会显示父组件传的内容

具名插槽

很多时候子组件都不止一个slot,我们可能允许调用者同时传入多个slot,这个时候为了区分插槽与内容的对应关系,我们可以分别给 slot 和内容都加上一个名字,插入插槽的时候大家按照名字区分好就可以了,这就是具名插槽

1.基本使用

给子组件child.vue添加3个slot 两个有name,一个没有name

<template>
  <div class="child-con">
    <p>我是子组件2</p>
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

父组件 根据name添加内容, 简写:v-slot:header可以简写成#header

<template>
  <div class="test-con">
    <p>我是父组件1</p>
    <child>
      <template v-slot:header>
        <div>我是 header:{{ message }}</div>
      </template>
      <div>我没有name:{{ message }}</div>
      <template v-slot:footer>
        <div>我是 footer:{{ message }}</div>
      </template>
    </child>
  </div>
</template>
<script setup lang="ts">
import Child from "./components/child.vue";
import { ref } from "vue";
const message = ref("这是父组件向子组件插入的message");
</script>

此时页面

image-20231009153932597

由上面页面可以看出,我们传入的内容都渲染到了对应的插槽内,没有命名的插槽渲染了我们传入的未添加指令的内容。

2.动态插槽名

前面我们给插槽命名的时候都是直接写死的,其实我们有时候可以动态给插槽命名的,以满足更多的业务场景slotName可以动态传

<template v-slot:[slotName]>

插槽作用域问题

面父组件代码中 message 是我们在父组件中定义的数据,但是在我们的子组件 child 中渲染了出来,说明子组件中的插槽是可以访问到父组件中的数据作用域的,但是反过来是不行的,因为我们无法通过插槽拿到子组件的数据。但是,万一我们有需求就是需要在插槽内容中获取子组件数据怎么办呢?

子组件child.vue

<template>
  <div class="child-con">
    <p>我是子组件2</p>
    <header>
      <slot text="我是子组件的text" :count="1" name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

父组件 v-slot:header=""接收 也可以简写成#header=""

<template>
  <div class="test-con">
    <p>我是父组件1</p>
    <child>
      <template v-slot:header="{ text, count }">
        <div>{{ text }}---我是子组件的count:{{ count }}</div>
        <div>我是 header:{{ message }}</div>
      </template>
      <div>我没有name:{{ message }}</div>
      <template v-slot:footer>
        <div>我是 footer:{{ message }}</div>
      </template>
    </child>
  </div>
</template>

此时页面image-20231009160902086

水平有限有问题欢迎在评论区指出,一起讨论探索,如果对您有帮助,请点赞和收藏哦 感谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值