# 1.slot 中默认内容

vue
// App.vue
<template>
  <div>
    <!-- 大写的组件名可写成小写用 - 相连 -->
    <my-slot-cpn></my-slot-cpn>
    <my-slot-cpn></my-slot-cpn>
    <my-slot-cpn></my-slot-cpn>
  </div>
</template>
<script>
  import MySlotCpn from './MySlotCpn.vue';
  export default {
    components: {
      MySlotCpn
    }
  }
</script>
<style scoped></style>
vue
// MySlotCpn.vue
<template>
  <div>
    <h3>组件开始</h3>
    <slot>
      <span>我是默认的span元素</span>
    </slot>
     <slot>
      <p>我是默认的p元素</p>
    </slot>
    <h3>组件结束</h3>
  </div>
</template>
<script>
  export default { }
</script>
<style scoped></style>

参考结果:

slot_default

# 2. 替换 slot 中的元素

vue
// App.vue
<template>
  <div>
    <!-- 大写的组件名可写成小写用 - 相连 -->
    <my-slot-cpn>
      <h3>我插入了一个h3标签</h3>
    </my-slot-cpn>
    <my-slot-cpn></my-slot-cpn>
  </div>
</template>
<script>
  import MySlotCpn from './MySlotCpn.vue';
  export default {
    components: {
      MySlotCpn
    }
  }
</script>
<style scoped></style>

参考结果:slot_default_replace

# 3. 具名插槽 name

vue
// App.vue
<template>
  <div>
    <nav-bar :name="name">
     <!-- 完整写法:v-slot: -->
      <template v-slot:left></template>
      <!-- 简写:(v-slot:) 替换为字符 # -->
      <template #center>  
        <a>左边的a标签</a>
      </template>
      <template #right>
        <span>中间的span</span>
      </template>
      <!-- 直接使用 name,代表是叫 name 的插槽,必须用 v-slot:[name] -->
      <template #[name]>
        <button>右边的按钮</button>
      </template>
    </nav-bar>
  </div>
</template>
<script>
  import NavBar from './NavBar.vue';
  export default {
    components: {
      NavBar
    },
    data() {
      return {
        name: "Neko"
      }
    }
  }
</script>
<style scoped></style>
vue
// NavBar.vue
<template>
  <div class="nav-bar">
    <!-- 使用 name 给 slot 起个名字 -->
    <!-- 不写 name 默认 === <slot name="default"></slot> 这种写法 -->
    <div class="left">
      <slot name="left"></slot>
    </div>
    <div class="center">
      <slot name="center"></slot>
    </div>
    <div class="right">
      <slot name="right"></slot>
    </div>
    <!-- 动态插槽名 name -->
    <div class="addition">
      <slot :name="name"></slot>
    </div>
  </div>
</template>
<script>
  export default {
    // 使用 props 接收
    props: {
      name: String
    }
  }
</script>
<style scoped>
  .nav-bar {
    display: flex;
  }
  .left, .right, .center {
    height: 44px;
  }
  .left, .right, .addition {
    width: 80px;
    background-color: red;
  }
  .center {
    flex: 1;
    background-color: pink;
  }
</style>

参考结果:

slot_named

# 4. 作用域插槽

vue
// App.vue
<template>
  <div>
    <show-names :names="names">
      <!-- 没有名字默认是 default -->
      <template v-slot:default>
      </template>
    </show-names>
    <show-names :names="names">
      <!-- 赋一个值 slotProps,从这个 slotProps 里面取出属性。slotProps 可随意起名  -->
      <template v-slot="slotProps">
        <strong>{{ slotProps.item }}-{{ slotProps.index }}</strong>
      </template>
    </show-names>
    <!-- 独占默认插槽缩写 可以不使用 template -->
    <show-names :names="names" v-slot="Neko">
      <button>{{ Neko.item }}-{{ Neko.index }}</button>
    </show-names>
    <!-- 注意:如果还有其他的具名插槽,那么默认插槽也必须使用 template 来编写 -->
    <show-names :names="names">
      <template v-slot:default="Neko">
        <button>{{ Neko.item }}-{{ Neko.index }}</button>
      </template>
      <template v-slot:Neko>
        <h2>我是Neko</h2>
      </template>
    </show-names>
  </div>
</template>
<script>
  import ShowNames from './ShowNames.vue';
  export default {
    components: {
      ShowNames
    },
    data() {
      return {
        names: ["Neko", "Nico", "Aimer", "Aphrodite"]
      }
    }
  }
</script>
<style scoped></style>
vue
// ShowNames.vue
<template>
  <div>
    <template v-for="(item, index) in names" :key="item">
      <!-- 定义属性:item :index -->
      <slot :item="item" :index="index"></slot>
      <slot name="Neko">--default--</slot>
    </template>
  </div>
</template>
<script>
  export default {
    props: {
      names: {
        type: Array,
        default: () => []
      }
    }
  }
</script>
<style scoped></style>

参考结果:

Scope_slot