默认插槽(匿名插槽)

在子组件的 template 中添加 <slot></slot>

<!-- 子组件 -->
<template id="cpn">
  <!-- 组件里有多个标签时要在外层套一个div -->
  <div>
    <h3>我是子组件</h3>
    <slot></slot> <!-- 插槽,有多少个<slot></slot>,就会将父组件<cpn>标签之间的内容重复多少遍 -->
  </div>
</template>

父组件中可以在子组件标签中插入内容代替 <slot>

<!-- 父组件 -->
<div id="myapp">
  <cpn>自定义内容</cpn>
</div>

默认值(后备内容):插槽可以指定默认的显示,如果父组件不指定插槽的内容,则显示默认定义的

<!-- 子组件 -->
<template id="cpn">
  <!-- 组件里有多个标签时要在外层套一个div -->
  <div>
    <h3>我是子组件</h3>
    <p>哈哈哈</p>
    <slot>默认值</slot> <!-- 父组件没用传入内容时显示默认值 -->
  </div>
</template>

具名插槽

有多个插槽时,可以指定所替换的插槽

<!-- 子组件 -->
<template id="cpn">
  <div>
    <slot name="left"></slot>
    <slot name="center"></slot>
    <slot name="right"></slot>
  </div>
</template>
 
<!-- 父组件 -->
<div id="myapp">
  <cpn>
    <template v-slot:left>
      <button>左边</button>
    </template>
    
    <template v-slot:center>
      <span>中间</span>
    </template>
    
    <template v-slot:right>
      <button>右边</button>
    </template>
  </cpn>
</div>

注意:一个不带 name 的 <slot> 出口会带有隐含的名字 “default”

作用域插槽

让父组件中的插槽可以访问子组件中才有的数据

编译作用域:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的
为了实现父级模板里能够访问子级内容,需要在子组件的 slot 标签上绑定属性

 <!-- 父组件模板 -->
<div id="myapp">
  <cpn>
    <template v-slot:myslot="props">
      <span>{{ props.cdata }}</span>
    </template>
  </cpn>
</div>
 
<!-- 子组件模板 -->
<template id="cpn">
  <!-- 组件里有多个标签时要在外层套一个div -->
  <div>
    <slot name="myslot" :cdata="message"></slot>
  </div>
</template>
 
<script>
  // 父组件
  const myapp = new Vue({
    el: '#myapp',
    data: {
      message: '父组件的值'
    },
    // 子组件
    components: {
      cpn: {
        template: '#cpn',
        data() {
          return {
            message: 'hello'
          }
        }
      }
    },
  })
</script>

子组件绑定其作用域中的 message(即 ‘hello’ )到 cdata 上,父组件拿到键值对 cdata: hello 绑定到 props 上,最后父组件通过 props 访问 cdata 的值。(props 可以自定义命名)

缩写

v-slot:xxx 可以简写为 #xxx