Vue3插槽-看不会你给我一拳

149 阅读2分钟

1.插槽的介绍

我们都清楚父组件可以给儿子组件传递数据,但是如何通过父组件给儿子组件传递内容?很明显,插槽就诞生了。

2.插槽常见作用

  1. 父组件给儿子组件传递内容
  2. 父组件给儿子组件传递数据
  3. 儿子组件给父组件传递数据

3.插槽分类

  1. 匿名插槽
  2. 具名插槽
  3. 作用域插槽

4.不同插槽的介绍

4.1 匿名插槽

4.1.1父组件给儿子插槽不传递内容

Father.vue

<template>
  <div>Father</div>
  <Son/>
</template>

Son.vue

<template>
  <div>Son</div>
  <slot>
    <div>son title</div>
  </slot>
</template>

输出结果:

image.png

总结:当父组件给儿子插槽不传递内容时,儿子的插槽使用自己的内容。

4.1.2父组件给儿子插槽传递内容

Father.vue

<template>
  <div>Father</div>
  <Son>
      <div>son tiltle</div>
      <div>son content</div>
      <div>son footer</div>
  </Son>
</template>

Son.vue

<template>
  <div>Son</div>
  <slot>
    <div>son title</div>
  </slot>
</template>

输出结果:

image.png

总结:父组件给儿子组件的插槽传递数据时,会使用父组件给儿子插槽传递的内容,儿子插槽自定义的内容会被覆盖掉。

4.2 具名插槽(有名称的插槽)

考虑如果子组件有多个插槽,父组件如果想给指定插槽传递指定的内容,如何传递?我们先看看匿名插槽的结果,很明显乱的一批儿子组件插槽内容都一样。

Father.vue

<template>
  <div>Father</div>
  <Son>
    <div>son tiltle</div>
    <div>son content</div>
    <div>son footer</div>
  </Son>
</template>

Son.vue

<template>
  <div>Son</div>
  <slot></slot>
  <slot></slot>
</template>

结果是:

image.png

具名插槽正确姿势

  1. 儿子组件的slot添加属性name='xxx'标记对应插槽的名称
  2. 父组件在儿子组件内部添加template标签,并添加#属性绑定对应儿子组件插槽的name值

Father.vue

  <template>
  <div>Father</div>
  <Son>
     <!--对应header插槽-->
    <template #header>
      <div>header</div>
    </template>
    
      <!--对应content插槽-->
    <template #content>
      <div>content</div>
    </template>
    
     <!--对应footer插槽-->
    <template #footer>
      <div>footer</div>
    </template>
  </Son>
</template>

Son.vue

 <template>
  <div>Son</div>
  <slot name="header"></slot>
  <slot name="content"></slot>
  <slot name="footer"></slot>
</template>

结果:

image.png

根据结果分析知:具名插槽是有名称的,指定名称的插槽内容渲染到指定的插槽区域。

4.2 作用域插槽(插槽的传值)

作用域插槽研究的是:父组件的值如何通过插槽传递到儿子,儿子的值通过插槽如何传递给父亲。

父传子

插槽默认下,父组件的值可以直接通过插槽传递给儿子。十分方便

Father.vue

<template>
  <div>Father</div>
  <Son>
    <template #header>
      <div>{{age}}</div>
    </template>
  </Son>
</template>
<script lang='ts' setup>
import Son from "@/views/home/components/Son.vue"
import {ref} from "vue"
const age = ref(22)
</script>

Son.vue

<template>
  <div>Son</div>
  <slot name="header"></slot>
</template>

结果:

image.png

结论:父组件可以直接将数据通过插槽传递给儿子使用

子传父

父组件无法直接获取到儿子组件插槽定义的数据,必须通过指定方法完成。

子传父步骤:

  1. 儿子组件直接在插槽slot上定义数据

     <slot age=22></slot>
    
  2. 父亲在儿子插槽上任意定义数据获取传递的数据

     //如果是匿名插槽,匿名插槽本质上名称是default,info不是固定的,随便命名
     <Son #default='info'>
         {{info.age}}
     </Son>
     
     //如果是具名插槽,具名插槽是通过template标签包裹,info不是固定的,随便命名
     <Son>
         <template #name='info'>
             {{info.age}}
         <template/>
     </Son>
     
     
    

实例1

Father.vue

 <template>
  <div>Father</div>
  <Son>
  
    <!--匿名插槽-->
    <template #default='info1'>
      <div>默认插槽的数据{{info1.age}}</div>
    </template>
    
    <!--有名插槽-->
    <template #header='info2'>
      <div>header插槽的数据{{info2.age}}</div>
    </template>
  </Son>
</template>

Son.vue

 <template>
  <div>Son</div>
  <slot age=22></slot>
  <slot name='header' age=23></slot>
</template>

结果展示:

image.png 这个是匿名插槽和有名插槽的混合,二者子组件的插槽传递给各自的父组件。