为了让组件可以组合,需要一种方式来混合父组件的内容与子组件自己的模板。这个过程称为内容分发,使用特殊的<slot>
元素作为原始内容的插槽首先需要明确在哪个作用域编译父组件模板的内容在父组件作用域编译;子组件模板在子组件的作用域内编译
官方文档
单个插槽
当子组件中不包含<slot>
插口时,父组件传入的内容会被丢弃,当子组件的模板只有一个没有属性的插槽时 ,父组件传入的整个内容片段将插入到插槽所在的DOM 位置,并替换点插槽标签本身
最初在 <slot>
标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。
子组件
<div>
<slot>
只有在没有要分发的内容时才会显示。
</slot>
</div>
父组件
<div>
<child>
<p>这是一些初始内容</p>
<p>这是更多的初始内容</p>
</child>
</div>
具名插槽
<slot>
元素可以用一个特殊的特性 name 来进一步配置如何分发内容。多个插槽可以有不同的名字。具名插槽将匹配内容片段中有对应 slot 特性的元素。仍然可以有一个匿名插槽,它是默认插槽,作为找不到匹配的内容片段的备用插槽。如果没有默认插槽,这些找不到匹配的内容片段将被抛弃。
子组件
<div>
<h1>我是Home组件</h1>
<slot name="header">
<p>这是一个具名插槽</p>
</slot>
<main>
<slot>这是单个插槽</slot>
</main>
<slot name="footer">
<p>这是另一个具名插槽</p>
</slot>
</div>
父组件
<div>
<home>
<p>若不指定slot的name值,则默认为没有使用过的具名插槽或者匿名插槽,如果子组件中没有其他具名插槽或者匿名slot,则此处的内容会丢失</p>
<p slot="footer">这是name属性为footer的插槽需要显示的内容</p>
</home>
</div>
作用域插槽
作用域插槽可以用作一个能被传递数据的可重用模板,来代替已经渲染元素。在子组件中只要将数据传递到插槽,就像将prop传递给组件一样,可以实现子组件向父组件之间的传值:在父级中,具有特殊特性 slot-scope 的 <template>
元素必须存在,表示它是作用域插槽的模板。slot-scope 的值将被用作一个临时变量名,此变量接收从子组件传递过来的 prop 对象:在 2.5.0+,slot-scope 能被用在任意元素或组件中而不再局限于 <template>
。
子组件
<template>
<slot msg="hello">这是作用域插槽</slot>
</template>
父组件
<div>
<home>
<p slot-scope="data">
<a href="#">{{data.msg}}</a>
</p>
</home>
</div>
作用域插槽也可以是具名,它的典型用法是在列表中的渲染中,允许使用者自定义如何渲染列表的每一项:
父组件
<div>
<home>
<!--slot-scope的值实际上是一个可以出现在函数签名参数位置的合法的 JavaScript 表达式。所以可以使用解构赋值-->
<li slot="list" slot-scope="{msg}">{{msg}}</li>
<!--<li slot="list" slot-scope="props">{{props.msg}}</li> -->
</home>
</div>
子组件
<template>
<div>
<ul>
<slot name="list"
v-for="option in dataList"
:msg="option">这是具名作用域插槽</slot>
</ul>
</div>
</template>