slot 又名插槽,是 Vue 的内容分发机制,组件内部的模板引擎使用slot 元素作为承载分发内容的出口。插槽 slot 是子组件的一个模板标签元素,而这一个标签元素是否显示,以及怎么显示是由父组件决定的。slot 又分三类,默认插槽,具名插槽和作用域插槽。
默认插槽(Default Slot):
- 默认插槽是最简单的插槽类型,用于传递未命名的内容到子组件。
- 在父组件中,可以通过在子组件的标签内放置内容来传递数据。
- 一个组件内只有有一个匿名插槽。
html
<!-- Parent Component -->
<template>
<app-child>
This content will be placed in the default slot.
</app-child>
</template>
html
<!-- Child Component -->
<template>
<div>
<slot></slot>
</div>
</template>
具名插槽(Named Slot) :
- 具名插槽允许在父组件中将内容传递到特定的插槽位置。
- 在子组件中使用
<slot>
元素的name
属性为插槽命名。 - 一个组件可以出现多个具名插槽。
html
<!-- Parent Component -->
<template>
<app-child>
<template v-slot:header>
Content for the header slot.
</template>
<template v-slot:footer>
Content for the footer slot.
</template>
</app-child>
</template>
html
<!-- Child Component -->
<template>
<div>
<header>
<slot name="header"></slot>
</header>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
作用域插槽(Scoped Slot) :
- 作用域插槽允许子组件向父组件传递数据,使父组件能够使用子组件的数据。
- 在子组件中使用
<slot>
元素的name
属性,并使用v-bind
绑定传递的数据。
html
<!-- Parent Component -->
<template>
<app-child>
<template v-slot:default="slotProps">
{{ slotProps.message }}
</template>
</app-child>
</template>
html
<!-- Child Component -->
<template>
<div>
<slot :message="childMessage"></slot>
</div>
</template>
<script>
export default {
data() {
return {
childMessage: 'This message is from the child component.'
};
}
}
</script>
实现原理
-
子组件实例化时获取父组件传入的 slot 内容:
- 当子组件被实例化时,Vue.js会执行组件的生命周期钩子函数,其中
created
是一个常用的钩子。在created
钩子中,可以通过访问this.$slots
属性来获取父组件传递的插槽内容。
javascript// 子组件 created() { this.$slot = this.$slots; }
这样,
this.$slot
中就包含了所有插槽的内容,包括默认插槽和具名插槽。 - 当子组件被实例化时,Vue.js会执行组件的生命周期钩子函数,其中
-
插槽内容存放在 vm.$slot 中:
- 默认插槽的内容可以通过
this.$slot.default
来获取,而具名插槽的内容可以通过this.$slot.xxx
来获取,其中xxx
是具体的插槽名称。
javascript// 子组件 created() { this.$slot = this.$slots; this.defaultSlotContent = this.$slot.default; this.namedSlotContent = this.$slot.xxx; // Replace 'xxx' with the actual slot name }
这样,你就能在子组件中访问到父组件传递过来的不同插槽的内容。
- 默认插槽的内容可以通过
-
组件执行渲染函数时替换 slot 标签:
- 在子组件的渲染函数中,可以通过访问
this.$slots
来获取插槽的内容,并将其用于替换模板中的<slot>
标签。
javascript// 子组件的渲染函数 render(h) { return h('div', [ // 使用 this.$slots.default 替换默认插槽 h('div', this.$slots.default), // 使用 this.$slots.xxx 替换具名插槽 h('div', this.$slots.xxx), // Replace 'xxx' with the actual slot name ]); }
这样,当子组件渲染时,插槽的内容就会被动态地插入到相应的位置。
- 在子组件的渲染函数中,可以通过访问
-
作用域插槽的实现:
- 作用域插槽是通过在渲染函数中使用
this.$scopedSlots
来实现的。作用域插槽的内容可以通过函数调用,并传递数据给父组件。
javascript// 子组件的渲染函数 render(h) { return h('div', [ // 使用作用域插槽,并传递数据给父组件 this.$scopedSlots.default({ message: 'Hello from child!' }), ]); }
在父组件中,可以通过具名插槽的方式接收这个数据。
html<!-- 父组件模板 --> <template> <app-child> <template v-slot:default="slotProps"> {{ slotProps.message }} </template> </app-child> </template>
- 作用域插槽是通过在渲染函数中使用
通过以上步骤,实现了一个简单的插槽系统,支持默认插槽、具名插槽和作用域插槽。这种实现方式是Vue.js插槽机制的基础,它通过渲染函数和组件实例之间的关系来实现插槽的内容分发和数据传递。