Vue过去对于插槽的使用基本依赖于slot以及slot-scope(默认插槽|具名插槽|作用域插槽),但是现在这个两个attribute已经被v-slot
指令所取代(Vue2.6.0);
这两个attribute虽然已经被官方废弃且不会出现在 Vue 3 中,但在接下来所有的 2.x 版本中 slot
和 slot-scope
attribute 仍会被支持;
1、默认插槽(未改变)
不需要声明name或者作用域,直接进行使用,一个组件中只能有一个该类插槽:
// 父组件
<template>
<div class="father">
<h3>父组件</h3>
<子组件名称>
<div class="father_write_text">
<span>给子组件的文字</span>
</div>
</子组件名称>
</div>
</template>
// 子组件
<template>
<div class="child">
<h3 class="child_title">子组件</h3>
<slot></slot>
</div>
</template>
// 效果
<div class="father">
<h3>父组件</h3>
<div class="child">
<h3 class="child_title">子组件</h3>
// slot标签被父组件的信息替换
<div class="father_write_text">
<span>给子组件的文字</span>
</div>
</div>
</div>
2、具名插槽
2.x: 具名插槽顾名思义,就是有名字(slot=“” / name)的插槽,可以在组件中使用多个:
// 父组件
<template>
<div class="father">
<h3>父组件</h3>
<子组件名称>
<div class="father_write_text" slot="msg_1">
<span>name为msg_1的数据</span>
</div>
<div class="father_write_text" slot="msg_2">
<span>name为msg_2的数据</span>
</div>
<div class="father_write_text">
<span>默认插槽</span>
</div>
</子组件名称>
</div>
</template>
// 子组件
<template>
<div class="child">
// 具名插槽 name = msg_1
<slot name="msg_1"></slot>
<h3 class="child_title">子组件</h3>
// 具名插槽 name = msg_2
<slot name="msg_2"></slot>
// 默认插槽
<slot></slot>
</div>
</template>
// 总结:父组件有slot声明名字并在子组件通过slot name=""调用的就是具名插槽
v-slot:
// 父组件
<template>
<div class="father">
<h3>父组件</h3>
<子组件名称>
<template v-slot:msg_1>
<div class="father_write_text">
<span>name为msg_1的数据</span>
</div>
</template>
<template v-slot:msg_2>
<div class="father_write_text">
<span>name为msg_2的数据</span>
</div>
</template>
<template v-slot:default>
<div class="father_write_text">
<span>默认插槽</span>
</div>
</template>
</子组件名称>
</div>
</template>
// 子组件
<template>
<div class="child">
// 具名插槽 name = msg_1
<slot name="msg_1"></slot>
<h3 class="child_title">子组件</h3>
// 具名插槽 name = msg_2
<slot name="msg_2"></slot>
// 默认插槽
<slot></slot>
</div>
</template>
// 总结:父组件有template且用v-slot指令声明名字并在子组件通过slot name=""调用的就是具名插槽,而默认插槽在v-slot指令中默认为v-slot:default
3、作用域插槽
2.x: 能够将父组件数据带入子组件,并能在一个范围(域)内打点调用数据的插槽:
// 父组件
<template>
<div class="father">
<h3>父组件</h3>
<子组件名称>
<template slot-scope="user">
<div class="father_write_text">
<span v-for="item in user.data">{{item}}</span>
</div>
</template>
</子组件名称>
</div>
</template>
// 子组件 data: ['msg_1','msg_2']
<template>
<div class="child">
<h3 class="child_title">子组件</h3>
<slot :data="data"></slot>
</div>
</template>
// 效果
<div class="father">
<h3>父组件</h3>
<div class="child">
<h3 class="child_title">子组件</h3>
// slot标签被父组件的结构替换, 但是其中信息则是子组件的data
<div class="father_write_text">
<span>msg_1</span>
<span>msg_2</span>
</div>
</div>
</div>
// 总结:由父组件提供数据展示的样式,而子组件负责提供数据的就是作用域插槽,假设子组件上是<slot :num="100" :a="1"></slot> ,则父组件接受到的对象user就是 {num: 100, a: 1}
v-slot:
// 父组件
<template>
<div class="father">
<h3>父组件</h3>
<子组件名称>
<template v-slot:default="user">
<div class="father_write_text">
<span v-for="item in user.data">{{item}}</span>
</div>
</template>
</子组件名称>
</div>
</template>
// 子组件 data: ['msg_1','msg_2']
<template>
<div class="child">
<h3 class="child_title">子组件</h3>
<slot :data="data"></slot>
</div>
</template>
// 效果
<div class="father">
<h3>父组件</h3>
<div class="child">
<h3 class="child_title">子组件</h3>
// slot标签被父组件的结构替换, 但是其中信息则是子组件的data
<div class="father_write_text">
<span>msg_1</span>
<span>msg_2</span>
</div>
</div>
</div>
// 总结:由父组件提供数据展示的样式同时用v-slot=“”接收,而子组件负责提供数据的就是作用域插槽,假设子组件上是<slot :num="100" :a="1"></slot> ,则父组件接受到的对象user就是 {num: 100, a: 1}
注意:
v-slot
也有缩写,即把参数之前的所有内容 (v-slot:
) 替换为字符 #(v-slot:msg_1 === #msg_1)--具名|(#test="user")--作用域
除独占默认插槽的缩写语法外, v-slot 只能添加在一个 <template> 上
独占默认插槽的缩写语法:
当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot
直接用在组件上:
<子组件 v-slot:default="user">
{{ user.data.firstName }}
</子组件>
如果子组件下还有其他的插槽,那么就不能这样使用,因为默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确(明确-独占两个字)