vue3 | slots

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    一、什么是插槽

    插槽就是子组件中的提供给父组件使用的一个占位符,用<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

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
    标签: vue