Vue.js 中的插槽(Slots)是Vue组件间进行内容传递的重要机制,用于在父组件中向子组件插入内容。以下是各类插槽的解释和用法:
匿名插槽 / 默认插槽:
- 当你在子组件中定义一个没有
name
属性的<slot>
标签时,它就是一个匿名插槽或默认插槽。 - 如果父组件没有明确指明要插入到哪个具名插槽,那么所有未分配的内容将自动填充到默认插槽中。
<!-- 子组件 --> <template> <div> <slot>这是默认插槽的默认内容</slot> </div> </template> <!-- 父组件 --> <MyComponent> <p>这段文本会插入到子组件的默认插槽中</p> </MyComponent>
- 当你在子组件中定义一个没有
具名插槽:
- 具名插槽允许你为特定区域定义名称,父组件可以按照名称将内容插入到子组件的不同位置。
<!-- 子组件 --> <template> <div> <h2><slot name="header"></slot></h2> <slot name="body"></slot> <footer><slot name="footer"></slot></footer> </div> </template> <!-- 父组件 --> <MyComponent> <template v-slot:header> <h3>这是页头</h3> </template> <template v-slot:body> <p>这是主体内容</p> </template> <template v-slot:footer> <p>这是页脚</p> </template> </MyComponent>
作用域插槽( Scoped Slots):
- 作用域插槽允许子组件向其插槽传递数据,让父组件可以在插槽内容中访问这些数据。
- 在 Vue 2.x 中使用
slot-scope
特性实现,在 Vue 3.x 中使用v-slot
指令及其参数语法实现。
<!-- Vue 2.x --> <!-- 子组件 --> <template> <ul> <li v-for="item in items"> <slot :item="item" slot-scope="{ item }">{{ item.text }}</slot> </li> </ul> </template> <!-- 父组件 --> <MyListComponent> <template slot="default" slot-scope="{ item }"> <strong>{{ item.title }}</strong>: {{ item.description }} </template> </MyListComponent> <!-- Vue 3.x --> <!-- 子组件 --> <script setup> const items = [/*...*/]; </script> <template> <ul> <li v-for="item in items"> <slot :item="item">{{ item.text }}</slot> </li> </ul> </template> <!-- 父组件 --> <MyListComponent> <template #default="{ item }"> <strong>{{ item.title }}</strong>: {{ item.description }} </template> </MyListComponent>
插槽默认值:
- 子组件可以为其插槽定义默认内容,当父组件没有提供相应插槽内容时,这个默认内容将会被展示出来。
- 在上面匿名插槽的例子中,“这是默认插槽的默认内容”就是默认值。
<!-- Vue 2.x -->
<!-- 子组件 -->
<template>
<ul>
<li v-for="item in items">
<slot :item="item" slot-scope="{ item }">{{ item.text }}</slot>
</li>
</ul>
</template>
<!-- 父组件 -->
<MyListComponent>
<template slot="default" slot-scope="{ item }">
<strong>{{ item.title }}</strong>: {{ item.description }}
</template>
</MyListComponent>
<!-- Vue 3.x -->
<!-- 子组件 -->
<script setup>
const items = [/*...*/];
</script>
<template>
<ul>
<li v-for="item in items">
<slot :item="item">{{ item.text }}</slot>
</li>
</ul>
</template>
<!-- 父组件 -->
<MyListComponent>
<template #default="{ item }">
<strong>{{ item.title }}</strong>: {{ item.description }}
</template>
</MyListComponent>