vue3 | slots

一、什么是插槽

插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot>  表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>标签,父组件填充的内容称为插槽内容

  • 子组件不提供插槽时,父组件填充失效
  • 父组件无填充时,<slot></slot>中的备用内容会启用生效
  • 父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子作用域中编译的,互不影响

二、匿名插槽(默认插槽)

介绍

在外部组件没有提供任何内容的情况下,可以使用匿名插槽提供默认内容。

使用场景

比如
MyComponent.vue

<n-el>
    <slot>这是一个默认展示的内容</slot>
</n-el>

//组件使用
<MyComponent/>

如下:

image.png

如果外部组件提供了插槽内容,我们提供的内容会覆盖掉默认的内容

如下:

<MyComponent>加入一段文字</MyComponent>

image.png

注: 插槽内容可以是任意合法的模板内容,不局限于文本。

如下:

<MyComponent>
  <n-button>加入一个按钮</n-button>
</MyComponent>

image.png

三、具名插槽

介绍

<slot>元素带有 name 属性的插槽被称为具名插槽。

使用场景

作用于一个组件中拥有多个插槽,而name相当于插槽的标识,用来给各个插槽分配唯一的 ID。

MyComponent.vue

<n-el class="flex flex-col justify-center items-center h-[80vh] w-full">
  <n-el class="text-[pink] text-[18px] mb-2">组件相关内容</n-el>
  <slot name="head"></slot>
  <slot name="main"></slot>
  <slot name="footer"></slot>
</n-el>

外部引用该组件

<MyComponent>
  <template v-slot:head>
    <n-el>这是头部内容</n-el>
  </template>
  <template v-slot:main>
    <n-el>这是主体内容</n-el>
  </template>
  <template v-slot:footer>
    <n-el>这是尾部内容</n-el>
  </template>
  <template v-slot:no>
    <n-el>组件中没有可匹配的插槽name,不显示</n-el>
  </template>
</MyComponent>

v-slot可以简写成#

    <MyComponent>
      <template #head>
        <n-el>这是头部内容</n-el>
      </template>
      <template #main>
        <n-el>这是主体内容</n-el>
      </template>
      <template #footer>
        <n-el>这是尾部内容</n-el>
      </template>
      <template #no>
        <n-el>组件中没有可匹配的插槽name,不显示</n-el>
      </template>
    </MyComponent>

现在  <template>  元素中的所有内容都将被传递到相应的插槽。

image.png

image.png

注意: 匿名插槽也有自己的name,只不过 name 会被隐式地命名为default

image.png

上面的写法等价于:

image.png

image.png

四、动态插槽名

<MyComponent>
  <template v-slot:[slotName]>
    ...
  </template>

  <!-- 缩写为 -->
  <template #[slotName]>
    ...
  </template>
</MyComponent>

如下
MyComponent.vue

<n-el>
  <n-el>组件相关内容</n-el>
  <slot name="head"></slot>
</n-el>
<script setup lang="ts">
  const data = 'head'
</script>
<template>
    ......
    <MyComponent>
      <template #[data]> 头部内容 </template>
    </MyComponent>
    .......
</template>

image.png

五、作用域插槽

介绍

作用域插槽可以让父级外层组件能够访问子组件的数据,子组件向将数据提供给插槽,组件 props 传递数据的方式,子组件向插槽传递一个attributes,父组件通过v-slot带的值(任意命名)来获取子组件的数据。

使用场景

(一)、默认插槽

MyComponent.vue

<n-el class="flex flex-col justify-center items-center h-[80vh] w-full">
  <slot content="螺蛳粉" data="10"></slot>
</n-el>

写法一: v-slot 写在组件上

   <MyComponent v-slot="res">
      <n-el>老板:来 {{ res.data }} 份 {{ res.content }} ~</n-el>
    </MyComponent>

image.png

注意: v-slot="res"  可以类比这里的函数签名,和函数的参数类似,我们也可以在  v-slot  中使用解构:

<MyComponent v-slot="{ data, content }">
  <n-el>
    老板:来 {{ data }} 份 {{ content }} ~
  </n-el>
</MyComponent>

写法二: v-slot 写在 template 上

   <MyComponent>
      <template v-slot:default="res">
        <n-el>老板:来 {{ res.data }} 份 {{ res.content }} ~</n-el>
      </template>

      //或者
      <template #default="res">
        <n-el>老板:来 {{ res.data }} 份 {{ res.content }} ~</n-el>
      </template>

    </MyComponent>

(二)、具名插槽

具名作用域插槽的工作方式也是类似的,插槽 props 可以作为  v-slot  指令的值被访问到:v-slot:name="slotProps"。当使用缩写时是这样:

MyComponent.vue

<n-el class="flex flex-col justify-center items-center h-[80vh] w-full">
  <slot content="北京烤鸭" data="5" name="food1"></slot>
  <slot content="长沙臭豆腐" data="15" name="food2"></slot>
</n-el>
   <MyComponent>
      <template #food1="res">
        <n-el>老板:来 {{ res.data }} 份 {{ res.content }} ~</n-el>
      </template>
      <template #food2="res">
        <n-el>老板:来 {{ res.data }} 份 {{ res.content }} ~</n-el>
      </template>
    </MyComponent>

image.png

posted @ 2023-02-07 20:12  杨芋可可  阅读(919)  评论(0编辑  收藏  举报