使用 vue 开发的项目中常常会进行组件的封装,在封装的过程中 slot 起着非常重要的作用。
编译作用域:父级模板的内容均在父级作用域中编译,子级模板的内容均在子级作用域中编译。
1. vue 2.6.0 版本之前
子组件 child.vue:
<template>
<div>
<span>hello!</span>
<!-- 默认插槽 -->
<slot>小明</slot>
<!-- 具名插槽 -->
<slot name="aa">爬山吗?</slot>
<slot name="bb" :config="item">这是?</slot>
</div>
</template>
父组件:
<template>
<child>
<span>qiuer</span>
<span slot="aa">你吃饭了吗?</span>
<div slot="bb" slot-scope="scope">
<span>{{ scope.config.label }}</span>
</div>
</child>
</template>
2. vue 2.6.0 之后
vue 2.6.0 起引入了 v-slot
2.1 当只有默认插槽无具名插槽时
子组件 child.vue :
<template>
<div>
<h1>hi~</h1>
<slot v-bind:user="user">
<div>路见不平一声吼~</div>
</slot>
<h1>end~</h1>
</div>
</template>
父组件:
<template>
<child v-slot="slotProps">
{{ slotProps.user.name }}
</child>
<!-- 或者 -->
<child v-slot="{ user }">
{{ user.name }}
</child>
<!-- 或者,将 user 重名为 person -->
<child v-slot="{ user: person }">
{{ person.name }}
</child>
<!-- 或者,定义后备内容,用于插槽 prop 是 undefined 的情形 -->
<child v-slot="{ user = { name: '小红' } }">
{{ user.name }}
</child>
<!-- 缩写:使用缩写必须具名 -->
<child #default="{ user }">
{{ user.name }}
</child>
</template>
2.2 具名插槽
当有多个插槽时,需要使用完整的插槽语法。
子组件 child.vue :
<template>
<div>
<div>
<slot name="aa"></slot>
</div>
<div>
<slot>
<a v-bind:href="url" class="nav-link">Submit</a>
</slot>
</div>
<div>
<slot name="bb" v-bind:user="user"></slot>
</div>
</div>
</template>
父组件:
<template>
<child url="/about">
<template v-slot:aa>
<h1>这是具名插槽 aa</h1>
</template>
<template v-slot:default>
关于我们
</template>
<template v-slot:bb="slotProps">
<h1>这是具名插槽 bb</h1>
<div>{{ slotProps.user.name }}</div>
</template>
<!-- 根据需求也可以使用动态插槽名 -->
<!-- <template v-slot:[dynamicSlotName]>
</template> -->
</child>
<!-- 缩写 -->
<child url="/about">
<template #aa>
<h1>这是具名插槽 aa</h1>
</template>
<template #default>
关于我们
</template>
<template #bb="{ user }">
<h1>这是具名插槽 bb</h1>
<div>{{ user.name }}</div>
</template>
</child>
</template>
2.3 默认插槽缩写不能与具名插槽混用
默认插槽缩写不能与具名插槽混用,因为混用会导致作用域不明确。以下是错误示例:
子组件 child.vue :
<template>
<div>
<div>
<slot v-bind:user="user">
<a v-bind:href="url" class="nav-link">Submit</a>
</slot>
</div>
<div>
<slot name="bb" v-bind:memu="item"></slot>
</div>
</div>
</template>
父组件:
<template>
<child url="/about" v-slot="slotProps">
{{ slotProps.user.name }}
<template v-slot:bb="otherSlotProps">
slotProps在此不可用
</template>
</child>
</template>
3. $slots
$slots
:组件插槽集,即组件所有插槽的集合(默认插槽、具名插槽)。例如:通过 this.$slots.default
获取组件的默认插槽。