在 Vue.js 中,<slot> 是一个非常重要的概念,用于实现组件间的动态内容插槽功能。通过 <slot>,父组件可以向子组件传递任意内容,这使得组件更加灵活和可复用。
<slot> 的基本用法:
-
默认插槽:
- 当没有指定
name属性时,<slot>表示默认插槽。 - 父组件可以将任意内容放置在子组件标签内,这些内容将会填充到子组件的
<slot>位置。
- 当没有指定
-
具名插槽:
- 通过
name属性定义具名插槽。 - 父组件使用
<template v-slot:name>或slot="name"(Vue 2)来指定要插入的内容。
- 通过
-
作用域插槽:
- 允许父组件访问子组件的数据或方法。
- 通过
v-slot指令结合变量名来定义作用域插槽。
下面是一些具体的示例来解释这些概念。
示例 1: 默认插槽
子组件 (ChildComponent.vue):
vue
深色版本
1<template>
2 <div>
3 <p>这是一个子组件。</p>
4 <slot></slot>
5 </div>
6</template>
父组件 (ParentComponent.vue):
vue
深色版本
1<template>
2 <div>
3 <child-component>
4 <p>这是从父组件传递过来的内容。</p>
5 </child-component>
6 </div>
7</template>
8
9<script>
10import ChildComponent from './ChildComponent.vue';
11
12export default {
13 components: {
14 ChildComponent,
15 },
16};
17</script>
示例 2: 具名插槽
子组件 (ChildComponent.vue):
vue
深色版本
1<template>
2 <div>
3 <header>
4 <slot name="header"></slot>
5 </header>
6 <main>
7 <slot name="main"></slot>
8 </main>
9 <footer>
10 <slot name="footer"></slot>
11 </footer>
12 </div>
13</template>
父组件 (ParentComponent.vue):
vue
深色版本
1<template>
2 <div>
3 <child-component>
4 <template v-slot:header>
5 <h1>这是头部内容</h1>
6 </template>
7 <template v-slot:main>
8 <p>这是主要内容</p>
9 </template>
10 <template v-slot:footer>
11 <p>这是底部内容</p>
12 </template>
13 </child-component>
14 </div>
15</template>
16
17<script>
18import ChildComponent from './ChildComponent.vue';
19
20export default {
21 components: {
22 ChildComponent,
23 },
24};
25</script>
示例 3: 作用域插槽
子组件 (ChildComponent.vue):
vue
深色版本
1<template>
2 <div>
3 <p>这是子组件的标题:{{ title }}</p>
4 <slot :title="title"></slot>
5 </div>
6</template>
7
8<script>
9export default {
10 data() {
11 return {
12 title: 'Hello World',
13 };
14 },
15};
16</script>
父组件 (ParentComponent.vue):
vue
深色版本
1<template>
2 <div>
3 <child-component>
4 <template v-slot="{ title }">
5 <p>{{ title }} 是从子组件传递过来的。</p>
6 </template>
7 </child-component>
8 </div>
9</template>
10
11<script>
12import ChildComponent from './ChildComponent.vue';
13
14export default {
15 components: {
16 ChildComponent,
17 },
18};
19</script>
注意事项:
- 在 Vue 2 中,使用
slot="name"来定义具名插槽。 - 在 Vue 3 中,推荐使用
v-slot:name语法来定义具名插槽,更加清晰且易于理解。 - 作用域插槽允许父组件访问子组件的数据或方法,增强了组件间的数据交互能力。
<!-- 定义: -->
<!-- <slot name="name" $slots.reference/> -->
<template>
<transfer-panel
ref="leftPanel"
:data="sourceData"
:option-render="optionRender"
:placeholder="panelFilterPlaceholder"
:title="leftPanelTitle"
:filterable="filterable"
:format="format"
:filter-method="filterMethod"
:default-checked="leftDefaultChecked"
:props="props.props"
@checked-change="onSourceCheckedChange"
>
<slot name="left-footer" />
<template v-if="$slots.reference">
<slot name="reference" />
</template>
</transfer-panel>
</template>
<!-- 使用: -->
<!-- #name v-slot:name slot="name" -->
<template>
<transfer-panel ref="leftPanel" :data="sourceData" :option-render="optionRender" :placeholder="panelFilterPlaceholder"
:title="leftPanelTitle" :filterable="filterable" :format="format" :filter-method="filterMethod"
:default-checked="leftDefaultChecked" :props="props.props" @checked-change="onSourceCheckedChange">
<template #left-footer>
<el-button class="transfer-footer" size="small">Operation</el-button>
</template>
<template #right-footer>
<el-button class="transfer-footer" size="small">Operation</el-button>
</template>
或者
<template #reference>
<el-button @click="visible = true">Delete</el-button>
</template>
或者
<el-button slot="reference" @click="visible = true">vue2的写法</el-button>
或者
<el-button v-slot:reference @click="visible = true">vue3的写法</el-button>
</transfer-panel>
</template>
<!-- 作品域插槽定义: -->
<template>
<div>
<p>这是子组件的标题:{{ title }}</p>
<slot :title="title"></slot>
</div>
</template>
<!-- 作品域插槽使用: -->
<child-component>
<template v-slot="{ title }">
<p>{{ title }} 是从子组件传递过来的。</p>
</template>
</child-component>