vue插槽(slot)的基本用法

345 阅读2分钟

插槽是vue为组件的封装者提供的能力,允许开发者在封装时,把不确定的、希望由用户指定的部分定义为插槽。 简单理解为 :为用户预留的内容占位符

基本使用

<!-- Left.vue 子组件中预留插槽 -->
<template>
    <div class="contianer">
        <h1>这是子组件</h1>
        <slot></slot>
        <!-- 
            插槽可以提供默认内容,当父组件没有提供自定义内容时,默认内容就会生效
          <slot>这是默认内容,父组件没有提供自定义内容就会生效</slot>
        -->
    </div>
</template>

<!-- App.vue 父组件使用子组件时,向插槽填充内容 -->
<template>
    <div>
        <Left>
            <!-- 默认下如果组件内没有定义插槽,在组件的内容节点中填写内容会默认被忽略。-->
            <p>这是在 Left 组件内容节点中,声明的 p 标签</p>
        </Left>
    </div>
</template>

<script>
    import Left from "@/components/Left.vue"
    export default {
        components:{
            Left
        }
    }
</script>

具名插槽

组件在预留插槽时可以设置 name 属性,表示当前插槽的名称(也叫具名插槽)

如果没有设置 name 名称的插槽默认名称为 default

父组件向具名插槽提供自定义内容注意点:

  • 如果要把内容填充到指定名称的插槽中,需要在包裹一个 <template> 标签,同时在 <template> 中通过 v-slot:名称 指定插槽的名称
  • v-slot:名称 简写形式为 #名称
  • <template> 是一个虚拟标签,只起到包裹性质的作用,但不会被渲染为实际性的HTML元素
  • 如果不指定插槽名称,那么自定义内容会被填充到所有的 default 插槽当中
  • 同一插槽填充多个内容,是追加不是覆盖
<!-- Left.vue 子组件-->
<template>
    <div class="contianer">
        <h1>这是子组件</h1>
        <!-- 具名插槽 -->
        <slot name="title">title 具名插槽</slot>
        <!-- 没有设置 name 名称则默认为 default (name="default"可以省略。默认就是这样)-->
        <slot name="default"></slot>
    </div>
</template>

<!-- App.vue 父组件 -->
<Left>
    <!-- 父组件向具名插槽 title 提供自定义内容 -->
    <!-- v-slot 指令只能使用在 template或组件 标签上 -->
    <!-- v-slot:名称  可以简写为  #名称 -->
  <template #title>
    <h1>《静夜思》</h1>
  </template>
</Left>

作用域插槽

作用域插槽就是在封装组件时,为预留的 <slot> 提供属性对应的值(数据)。

父组件向插槽提供自定义内容时,可以接收作用域插槽提供的数据。用等号的方式接收。如 #info="scope" ,在插槽的 template 标签内可以直接通过插值表达式或属性绑定等的方式访问到传递过来的数据。scope 默认为一个空对象,当有数据传递过来时,数据会存放在到 scope 对象中

/* Left.vue 子组件 */
<template>
  <div>
    <!-- 通过属性绑定的方式,为预留的 <slot> 提供数据 -->
    <slot name="info" :user="userinfo"></slot>
   </div>
</template>

<script>
  export default{
    data(){
      return{
        userinfo:{uname:"zs",age:18}
      }
    }
  }
</script>

/* App.vue 根组件*/
<Left>
    <!-- 这里也可以通过解构赋值的方式直接拿到需要的数据 -->
    <!-- <template #info="{uname,age}"> -->
  
  <template #info="scope">
    <h3>个人信息</h3>
    <!-- scope = {uname:"zs",age=18} -->
    <p>{{scope}}</p>  
   </template>
</Left>