vue中有几种插槽?

84 阅读4分钟

官网: cn.vuejs.org/guide/compo…

vue中插槽的定义:

指的是子组件中提供给父组件使用的一个占位符;
用标签<slot></slot>表示,父组件可以在这个占位符中填充任何模板代码,比如HTML、组件等,填充的内容会替换掉子组件的标签(替换占位符)。 在Vue中,有三种类型的插槽可用于组件间的内容分发: 默认插槽,具名插槽,作用域插槽

插槽的作用:

让父组件可以向子组件指定位置插入dom结构组件间通讯的一种方式,适用于父组件=>子组件

1、默认插槽(Default Slot) - 匿名插槽

默认插槽是最简单的一种插槽,就是通过替换占位符达到在父组件中更改子组件中内容的效果。默认插槽(匿名插槽)也是最常见的一种插槽类型。当组件没有具名插槽时,所有没有被包裹在具名插槽中的内容都会被放置在匿名插槽中。在组件模板中使用<slot></slot>标签来表示匿名插槽。

1.没有为插槽指定名称
2.通过slot标签可以添加匿名插槽
3.在使用组件的时候,组件中的内容会填充到所有匿名插槽的位置(虽多个匿名插槽不会报错, 但在开发中推荐只有一个匿名插槽)
4.匿名插槽可设置默认内容,如果没有传入内容就使用默认内容,如果传入了,就会进行覆盖
5.多个插槽混用时,v-slot不能省略default,需要严格使用template语法
--------------------------没有默认值------------------------------
// 在子组件中放置一个占位符(slot):
<template>  
    <div>
        <div>你是谁?</div>
        <slot></slot>  
    </div>  
</template>
export default {
    name: 'ChildComp',
}
// 父组件中引用这个子组件,并给这个占位符(slot)填充内容:
<template>  
    <div>
        <div>请问?</div>
        <ChildComp>
            <div>我是Alex</div>
        </ChildComp>  
    </div>  
</template>
// 页面实际展现内容:【请问? 你是谁?我是Alex】
--------------------------设置默认值------------------------------
// 在子组件中放置一个占位符(slot):
<template>  
    <div>
        <div>你是谁?</div>
        <slot>如果没有设置插入的标签,我就会出现</slot>
    </div>  
</template>
export default {
    name: 'ChildComp',
}
// 父组件中引用这个子组件,并给这个占位符(slot)填充内容:
<template>  
    <div>
        <div>请问?</div>
        <ChildComp></ChildComp>  
    </div>  
</template>
// 页面实际展现内容:【请问? 你是谁?如果没有设置插入的标签,我就会出现】

2、具名插槽(Named Slot)

具名插槽允许你在组件中定义多个插槽,并为它们命名。 父组件就可以根据插槽的名称将内容分发到相应的插槽中。 在组件模板中使用标签的<slot name="名称"></slot> 的name属性来表示具名插槽。

1.为slot设置名字的插槽就称为具名插槽  
2.一个封装组件中可以有多个具名插槽  
3.使用:通过template标签指定内容所放置的插槽名称  
4.使用简写:`v-slot:名字` 或者 `#名字`
Vue2.6.0, 具名插槽 和 作用域插槽 引入了一个新的统一的语法(即v-slot指令), 它取代了 slot 和 slot-scope 
在Vue2.6之前, 我们通过slot属性告诉Vue当前内容填充到哪一个具名插槽  
从Vue2.6开始, 我们通过v-slot指令告诉Vue当前内容填充到哪一个具名插槽
5.v-slot属性只可以在template标签使用
// 子组件
<template>  
    <div>  
        <slot name="header"></slot>  
        <slot name="content"></slot>  
        <slot name="footer"></slot>  
    </div>  
</template>
export default {
    name: 'ChildComp',
}
// 父组件使用具名插槽分发内容:
<template>  
    <ChildComp>  
        <template v-slot:header>  
            <div>我是header</div>
        </template>  
        // 等价于
        /*
        <template #header>  
            <div>我是header</div>
        </template>
        */  
        <template v-slot:content>  
            <div>我是content</div>
        </template>  
        <template v-slot:footer>  
            <div>我是footer</div>
        </template>  
    </ChildComp>  
</template>

3、作用域插槽(Scoped Slot)

作用域插槽允许子组件将数据传递给父组件,以便父组件可以在插槽中使用。 通过在子组件中使用标签的属性和具名插槽结合,可以将子组件的数据传递给父组件。 即:插槽绑定了props数据(除了name),这种带有props数据的插槽叫做"作用域插槽"

1.v-slot属性只可以在template标签使用, 
但只有默认值时,可以直接省略template, v-slot直接绑定到父组件
Vue2.6.0, 具名插槽 和 作用域插槽 引入了一个新的统一的语法(即v-slot指令), 它取代了 slot 和 slot-scope 
-----------------------匿名插槽---------------------------
// 子组件模板:
<template>  
    <div>  
        <slot :data="info"></slot>  
        // 等价于
        // <slot v-bind:data="info"></slot>  
    </div>  
</template>  
  
<script>  
export default {  
    name: 'ChildComp',
    data() {  
        return {  
            info: 'child',
        };  
    }  
};  
</script>
// 父组件使用作用域插槽获取子组件数据:
<template>  
    <ChildComp>
        <template v-slot:default="slotProps">  
            <p>{{ slotProps.data }}</p>  
        </template>  
        // 等价于
        /*
        <template v-slot="slotProps">  
            <p>{{ slotProps.data }}</p>  
        </template> 
        */ 
        // 等价于
        /*
        <template #default="slotProps">  
            <p>{{ slotProps.data }}</p>  
        </template> 
        */ 
    </ChildComp>  
    // 当提供的内容只有默认插槽时,可以直接在组件上使用v-slot:default="slotProps",甚至直接v-slot="slotProps"
即:下面两种方式与上面一种是等价的
    <ChildComp v-slot:default="slotPorp">
       <p>{{ slotProps.data }}</p>  
    </ChildComp>
    <ChildComp v-slot="slotPorp">
       <p>{{ slotProps.data }}</p>  
    </ChildComp>
</template>
-------------------------具名插槽--------------------------
// 子组件模板:
<template>  
    <div>  
        <slot 
         name="data"
         :gender="gender"
         :age="age"
         :username="username"
        ></slot>  
    </div>  
</template>   
<script>  
export default {  
    name: 'ChildComp',
    data() {  
        return {  
            gender: 'male',
            age: 18,
            username: 'alex'
        };  
    }  
};  
</script>
// 父组件使用作用域插槽获取子组件数据:
// 因为传递过来的数据是一个对象,所以可以用解构的方式来获取数据
// 也支持重命名v-slot="{age: newAge}" 和 定义默认值v-slot="{age = 20}"
<template>  
    <ChildComp>
        <template v-slot:data="{gender,age,username}">  
            <p>{{ username }}</p>  
            <p>{{ age }}</p>  
            <p>{{ gender }}</p>  
        </template>  
    </ChildComp>  
</template>

支持 动态插槽名

<ChildComp>
  <template v-slot:[dynamicSlotName]>
  </template>
  <!-- 等价于 -->
  <template #[dynamicSlotName]>
  </template>
</ChildComp>
<script>
export default {
  data() {
    return {
      dynamicSlotName: "header"
    };
  }
};
</script>