一
Vue 组件的插槽机制受原生 Web Component <slot> 元素的启发而诞生。Vue 组件通过插槽的方式实现内容的分法,它允许我们在父组件中编写 DOM 并在子组件渲染时把 DOM 添加到子组件的插槽中,使用起来非常方便。
在实现上,Vue 组件的插槽内容会被编译为插槽函数,插槽函数的返回值就是向槽位填充的内容。<slot>
标签则会被编译为插槽函数的调用,通过执行对应的插槽函数,得到外部向槽位填充的内容(即虚拟 DOM),最后将该内容渲染到槽位中。
插槽的用法
假设我们有一个名为 Demo 的子组件,它定义了一个插槽,并添加了 name 属性为 header (没有设置 name 属性则默认 name 是 default),它的模板如下
<header>
<slot name="header" />
</header>
然后在父组件中,可以这样使用这个子组件
<demo>
<template #header>
<h1>我是标题</h1>
</template>
</demo>
其中#
是v-slot
指令的简写,具体可见 v-slot
这里使用 template 标签(<template>
)和 v-slot
指令把父组件的 DOM 分发到子组件对应的插槽中,最终子组件(即,Demo 组件)渲染的 HTML 如下:
<header>
<h1>我是标题</h1>
</header>
这个例子演示了具名插槽的用法。
Tips :使用具名插槽,可以在组件中定义多个插槽,将多个插槽内容传入到各自目标插槽的出口。
二、作用域插槽
有些时候,我们希望父组件填充插槽内容的时候,可以使用子组件的一些数据,为了实现这个需求,Vue 提供了作用域插槽。我们可以像对组件传递 props 那样,向一个插槽的出口(slot 标签 <slot>
)上传递属性(attributes),而这个属性中的数据可以在父组件中被访问到!
假设我们有一个叫 Demo 的子组件,它的模板定义如下
<div>
<slot name="greet" msg="hello" />
</div>
其中 msg 为子组件在插槽的出口定义的一个属性,该属性可被父组件访问到。在父组件中可以这样使用这个子组件(即 Demo 组件)
<demo>
<template #greet="greetProps">
{
{ greetProps.msg }}
</template>
</demo>
其中 #
是 v-slot
指令的简写,具体可见 v-slot
注意,这里 v-slot
的值为 greetProps ,它是一个对象,它的值包含了子组件往 slot 标签中添加的属性,在我们这个例子中,v-slot
就包含了 msg 属性,然后我们就可以在父组件使用 greetProps.msg
获得子组件的数据,