在 Vue 3 中,setup
函数中处理插槽(Slots)与 Vue 2 中插槽的使用方式有一些不同,尤其是在处理具名插槽和作用域插槽时。Vue 3 通过 Composition API 和 setup
函数使插槽的管理更加灵活和简洁。
本文将详细介绍如何在 Vue 3 中使用默认插槽、具名插槽和作用域插槽,并通过实例讲解如何在 setup
函数中使用这些插槽。
一、Vue 3 插槽基础概念
插槽(Slots)是 Vue 中用于在子组件中插入动态内容的机制。父组件可以在子组件的插槽中传递 HTML 模板片段或数据。
1. 默认插槽
默认插槽用于在不具名的情况下,将父组件的内容插入到子组件的插槽位置。
2. 具名插槽
具名插槽允许我们定义多个插槽,每个插槽都可以有一个名称,父组件可以选择向指定插槽传递内容。
3. 作用域插槽
作用域插槽允许子组件将数据暴露给父组件,父组件可以根据这些数据来决定如何渲染插槽中的内容。
二、默认插槽的使用
默认插槽用于父组件向子组件传递内容,而不需要具名。
1. 父组件使用默认插槽
<template>
<div>
<h1>父组件</h1>
<ChildComponent>
<p>这是传递给子组件的内容</p>
</ChildComponent>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
};
</script>
2. 子组件接收默认插槽
在子组件中,我们可以通过 <slot>
标签来占位,表示父组件传递的内容将在此处被插入。
<template>
<div>
<h2>子组件</h2>
<slot></slot> <!-- 父组件传递的内容将插入到这里 -->
</div>
</template>
<script>
export default {
name: 'ChildComponent',
};
</script>
三、具名插槽的使用
具名插槽允许父组件通过指定的插槽名称来传递不同的内容。
1. 父组件使用具名插槽
<template>
<div>
<h1>父组件</h1>
<ChildComponent>
<template v-slot:header>
<h3>这是标题部分</h3>
</template>
<template v-slot:footer>
<p>这是页脚部分</p>
</template>
</ChildComponent>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
};
</script>
2. 子组件接收具名插槽
子组件通过 v-slot
指令或 <slot name>
来接收不同名称的插槽内容。
<template>
<div>
<h2>子组件</h2>
<div class="header">
<slot name="header"></slot> <!-- 具名插槽 "header" -->
</div>
<div class="footer">
<slot name="footer"></slot> <!-- 具名插槽 "footer" -->
</div>
</div>
</template>
<script>
export default {
name: 'ChildComponent',
};
</script>
四、作用域插槽的使用
作用域插槽允许子组件将内部的数据暴露给父组件,父组件根据这些数据决定如何渲染插槽内容。
1. 父组件使用作用域插槽
在父组件中,我们通过 v-slot
接收子组件暴露的参数,并可以动态渲染内容。
<template>
<div>
<h1>父组件</h1>
<ChildComponent>
<template v-slot:default="slotProps">
<p>来自子组件的数据:{{ slotProps.info }}</p>
</template>
</ChildComponent>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
};
</script>
2. 子组件暴露数据给作用域插槽
子组件通过 <slot>
标签暴露数据给父组件。在 Vue 3 的 setup
中,我们可以通过 slots.default
来使用插槽。
<template>
<div>
<h2>子组件</h2>
<slot :info="message"></slot> <!-- 暴露数据给父组件 -->
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const message = 'Hello from Child Component';
return { message };
}
});
</script>
五、在 setup
中使用插槽
在 Vue 3 的 setup
函数中,插槽通过 context.slots
来访问。我们可以使用 slots.default()
来渲染默认插槽内容,或者通过 slots.[name]()
来渲染具名插槽。
1. 默认插槽在 setup
中的使用
<template>
<div>
<h2>子组件</h2>
<div>
<slot></slot> <!-- 这里会插入默认插槽内容 -->
</div>
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { slots }) {
return () => (
<div>
<h2>子组件</h2>
<div>{ slots.default ? slots.default() : '无内容' }</div>
</div>
);
}
});
</script>
2. 具名插槽在 setup
中的使用
<template>
<div>
<slot name="header"></slot> <!-- 渲染 header 插槽 -->
<div>主体内容</div>
<slot name="footer"></slot> <!-- 渲染 footer 插槽 -->
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup(props, { slots }) {
return () => (
<div>
<div>{ slots.header ? slots.header() : '默认头部' }</div>
<div>主体内容</div>
<div>{ slots.footer ? slots.footer() : '默认尾部' }</div>
</div>
);
}
});
</script>
六、作用域插槽在 setup
中的使用
<template>
<div>
<slot :info="info"></slot> <!-- 将子组件数据暴露给父组件 -->
</div>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
const info = '从子组件传递的作用域数据';
return { info };
}
});
</script>
在父组件中,可以通过 v-slot
指令接收并使用子组件暴露的 info
数据:
<template>
<div>
<ChildComponent v-slot="{ info }">
<p>父组件接收到的作用域数据:{{ info }}</p>
</ChildComponent>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
};
</script>
总结
- 默认插槽:通过
<slot>
标签使用,父组件可以向子组件传递内容。 - 具名插槽:通过
v-slot:[name]
指令使用,允许在子组件内定义多个插槽位置。 - 作用域插槽:子组件可以暴露数据给父组件,父组件根据暴露的数据动态渲染内容。
- 在
setup
中使用插槽:通过context.slots
获取插槽内容,结合 JSX 或渲染函数可以灵活渲染插槽。
Vue 3 的插槽机制相比 Vue 2 更加灵活,在 setup
中使用插槽和暴露数据使得组件通信更加简洁。