插槽

@Slots
定义的组件除了传递属性 Props 和 传递事件 Emits,还可以传递内容 content - 通过插槽 slot / 预留位置插入内容,从而拓展功能 - more flexible and reusable
可以是任何有效的内容;静态数据,响应式数据,甚至其它组件 - can be any valid template content
可以指定插槽默认内容
可以声明多个插槽
为了区分,多个插槽应该指定 name 属性
插槽内容可以访问到父组件的数据作用域
更多信息,请访问 Slots插槽样式 Style / 组件样式
一个插槽
只预留一个位置
1. 子组件 Test.vue 创建过程中,预留一个位置/一个占位符,父组件传递进来的内容就会渲染在这里
<div>
  //其它内容
  <slot />
</div>
可以指定默认内容
<div>
  //其它内容
  <slot>插槽默认内容</slot>
</div>
2. 父组件 - 使用内容填充插槽;可以是普通文本,也可以是HTML节点
<Test>
  Something bad happened. 
</Test>
使用默认内容的插槽
<Test> </Test>
多个插槽
预留多个位置/多个插槽
使用属性 name 区分 - 具名插槽 Named Slots
没有指定 name 的,使用默认名字 default
同样可以指定默认内容
<div>
    //其它内容
    <slot></slot>
    <slot name = 'header'></slot>
    <slot name = 'footer'></slot>
</div>
使用具名插槽 - 使用 <template> 并指定对应的 v-slot 指令;可以简写为 #
<Test>  
  <template v-slot:header>
      <h1>Here might be a page title</h1>
  </template>
  <template #footer>
      <h1>Here might be a page footer</h1>
  </template>
</Test>
条件插槽*
条件插槽 Conditional Slots - 利用插槽的 $slots 属性判断
多用于具名插槽;只有当父组件提供了相应的插槽内容时,才会渲染对应的 DOM 结构;非条件插槽则必须使用
<div>
    //内容
    <slot></slot>
    <slot name = 'header'></slot>
    <div v-if="$slots.footer">
        <slot name = 'footer'></slot>
    </div>
</div>
使用条件插槽 - 不指定 footer
<Test>  
    <template v-slot:header>
        <h1>Here might be a page title</h1>
    </template>
</Test>
scoped slots
Slot content has access to the data scope of the parent component
Slot content does not have access to the child component's data
插槽作用域 - 插槽数据的访问
插槽可以使用父组件域内的数据
如果还想使用子组件域内的数据 - 子组件在渲染时将一部分数据提供给插槽
传递 props 那样,向一个插槽的出口上传递 attributes
接收插槽 props 时,默认插槽和具名插槽的使用方式有一些小区别;建议使用具名插槽
默认插槽
插槽组件 - 为默认插槽指定属性 msg 并绑定一个静态变量 msg
<template>
  <div>
    <div>Lorem ipsum dolor sit amet.</div>
    <slot :msg="msg"></slot>
  </div>
</template>

<script setup>
  let msg = 'hi,there.'
</script>
使用插槽组件 - 使用 v-slot 指定 属性对象名 并访问;属性对象名可以是任何合法标识符,建议使用 slot 作为前缀或者后缀,如 propsSlot;如果属性不匹配,并不会告警
<Test v-slot="propsSlot">;
  {{ propsSlot.msg }}
</Test>;
使用解构更简洁 - 省略了为属性命名的麻烦
<Test v-slot="{ msg }">;
  {{ msg }}
</Test>;
假设指定了多个属性
<Test v-slot="{{ msg, age }}">;
  {{ msg }} {{ age }}
</Test>;
具名插槽
插槽组件 - 为具名插槽指定 name 和属性 msg 并绑定一个静态变量 msg
<div>
  <div>Lorem ipsum dolor sit amet.</div>
  <slot name="greeting" :msg="msg"></slot>
</div>
指定具名插槽的同时,指定属性对象
<Test>
  <template #greeting="propsSlot">{{ propsSlot.msg }}</template>
</Test>
同样可以使用解构
<Test>
  <template #greeting="{ msg }">{{ msg }}</template>
</Test>
Summary & Homework
Summary
默认插槽
具名插槽
插槽作用域
v-slot
Homework
[] 版权组件进阶版 - 使用插槽,如果不指定内容则显示学院名字或小组名字
<template>
  <div class="copyright">
    <img class="img" :src='src' alt="">
    <slot>广州新华学院</slot>
    <div class="desc">2024 - 2026 © Copyright, powered by {{ id }}</div>
  </div>
</template>
[] 封装卡片组件,用户可以使用顶部标题和底部说明
[] 封装代码组件,以便区分是结构、逻辑还是样式