什么是插槽
插槽用于定义wrapper组件,这种wrapper组件相当于一个外壳组件,带有自己的样式和逻辑,内容却可以是动态的,即可以有各种不同的HTML。
当此wrapper组件被用在父组件中时,由父组件提供 HTML 代码给这个外壳组件。
而 slot 使 wrapper 组件能够从外部接收HTML 内容,这就是 slot 的作用。类似于props,只是props用于传递组件需要的数据,而 slot 则用于HTML 代码。
下面的例子中,一个组件BaseCard.vue
定义了slot,变成了一个wrapper 组件,可以接收HTML代码:
<template>
<div>
<!-- 可以从外部接收HTML 代码 -->
<slot></slot>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
div {
}
</style>
然后父组件 UerInfo.vue
可以像下面这样使用上面的组件:
<template>
<base-card>
<!-- Any content UserInfo needs -->
<p>...</p>
<div>...</div>
</base-card>
<template>
<script>
export default {
}
<script>
<style scoped>
</style>
named slots 命名插槽
未命名的slot只能有一个,是默认slot。如果一个组件有多个slot,可以为每个slot单独命名,告诉Vue 将模板内的内容放到对应的命名槽:
<template>
<div>
<header v-if="$slots.header">
<slot name="header"></slot>
</header>
<slot></slot>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
header {
}
div {
}
</style>
$slots
是 Vue 提供的另一个内置属性,它保存有此组件的不同插槽接收的数据的信息。
v-slot:
可以缩写为 #
, 因此下面代码中的 #header
等价于 v-slot:header
,如何使用具有命名插槽的wrapper组件:
<template>
<section>
<base-card>
<!-- 命名插槽 header -->
<template #header>
<h3>{{ fullName }}</h3>
<base-badge :type="role" :caption="role.toUpperCase()"></base-badge>
</template>
<!-- 默认插槽 -->
<template #default>
<p>{{ infoText }}</p>
</template>
</base-card>
</section>
</template>
<script>
export default {
props: ['fullName', 'infoText', 'role'],
};
</script>
如果 slot 没有接收到任何内容,那么这个 slot 可以render一些默认的内容,这样页面上仍然会有内容显示,例如:
<slot name="header">
<h2>The Default Content! Because nothing received! </h2>
</slot>
作用域插槽 scoped slots
某些时候,一个组件需要与他人共享,或在大型项目中以不同方式使用该组件,组件的某些方面必须可以定制。
作用域插槽使得将数据可以从定义插槽的组件内部传递到上一级parent组件,此组件在parent 组件中通过slot接收HTML code。
为了实现数据传递,可以在定义插槽的组件内部为slot添加props,然后这里设置的任何props都可以在为该slot传递数据的地方访问:
<template>
<ul>
<li v-for="goal in goals" :key="goal">
<slot :item="goal" another="placeholder"></slot>
</li>
</ul>
</template>
<script>
export default {
data() {
return {
goals: ['Finish the course', 'Learn Vue']
}
}
}
</script>
如何使用上面的组件:
<template>
<div>
<TheHeader />
<course-goals #default="slotProps">
<h2>{{slotProps.item}}</h2>
<p>{{slotProps.another}}</p>
</course-goals>
</div>
</template>
<script>
import CourseGoals from "./components/CourseGoals.vue";
export default {
components: {
CourseGoals,
},
},
};
</script>