插槽:在组件中设置,实质上是在dom树中预留位置,由调用此组件的组件插入数据,并非实质上的插入
1,举例:
//navigation-link 组件
<template>
<a v-bind:href="url" class="nav-link">
<slot></slot>
</a>
</template>
//组件
<navigation-link url="/profile">
Your Profile
</navigation-link>
//当组件渲染的时候,<slot></slot> 将会被替换为“Your Profile”。插槽内可以包含任何模板代码,包括 HTML:
<navigation-link url="/profile">
<!-- 添加一个 Font Awesome 图标 -->
<span class="fa fa-user"></span>
Your Profile
</navigation-link>
甚至其它的组件:
<navigation-link url="/profile">
<!-- 添加一个图标的组件 -->
<font-awesome-icon name="user"></font-awesome-icon>
Your Profile
</navigation-link>
如果 <navigation-link> 的 template 中没有包含一个 <slot> 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
,2,作用域
组用域在navigation-link组件中,而不是,父组件中,父组件仅作传递数据,
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
<!--
这里的 `url` 会是 undefined,
因为其 (指该插槽的) 内容是_传递给_ <navigation-link> 的
而不是 在 <navigation-link> 组件*内部*定义的。
-->
</navigation-link>
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
3,后备内容
当父组件无传递数据值,slot中的数据作为后备内容展示
<button type="submit">
<slot>Submit</slot>
</button>
4,具名插槽
组件
<template>
<div class="container">
<header>
<!-- 我们希望把页头放这里 -->
<slot name="header"></slot>
</header>
<main>
<!-- 我们希望把主要内容放这里 -->
<slot></slot>
//一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
</main>
<footer>
<!-- 我们希望把页脚放这里 -->
<slot name="footer"></slot>
</footer>
</div>
</template>
//对此,<slot> 元素有一个特殊的 attribute:name。这个 attribute 可以用来定义额外的插槽:
在向具名插槽提供内容的时候,我们可以在一个 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
//<template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。
5,作用域插槽(废弃)
<span>
<slot>{{ user.lastName }}</slot>
</span>
我们可能想换掉备用内容,用名而非姓来显示。如下:
<current-user>
{{ user.firstName }}
</current-user>
为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 元素的一个 attribute 绑定上去:
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 <slot> 元素上的 attribute 被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,但你也可以使用任意你喜欢的名字。
独占默认插槽的缩写语法
当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上:
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
这种写法还可以更简单。就像假定未指明的内容对应默认插槽一样,不带参数的 v-slot 被假定对应默认插槽:
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:
<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
<template v-slot:other="otherSlotProps">
slotProps is NOT available here
</template>
</current-user>
只要出现多个插槽,请始终为所有的插槽使用完整的基于 的语法:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user>
结构插槽
作用域插槽的内部工作原理是将你的插槽内容包裹在一个拥有单个参数的函数里:
function (slotProps) {
// 插槽内容
}
这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop,如下:
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
这样可以使模板更简洁,尤其是在该插槽提供了多个 prop 的时候。它同样开启了 prop 重命名等其它可能,例如将 user 重命名为 person:
<current-user v-slot="{ user: person }">
{{ person.firstName }}
</current-user>
你甚至可以定义后备内容,用于插槽 prop 是 undefined 的情形:
<current-user v-slot="{ user = { firstName: 'Guest' } }">
{{ user.firstName }}
</current-user>
5,动态插槽
格式:
<a v-bind:[attributeName]=“url”> attribute=ref—等价于–v-bind:ref
<a v-on:[eventName]=“doSomething”> … eventName=fouce–等价于–v-on:fouce
因为某些字符,如空格和引号,放在 HTML attribute 名里是无效的,所以动态参数不能使用这些字符
<a v-bind:[‘foo’ + bar]=“value”> …
方法:使用没有空格或引号的表达式,或用计算属性替代这种复杂表达式
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
6,具名插槽的缩写
v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #
该缩写只在其有参数的时候才可用
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
7,使用
或者直接把 slot attribute 用在一个普通元素上:
<base-layout>
<h1 slot="header">Here might be a page title</h1>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<p slot="footer">Here's some contact info</p>
<base-layout>
8,slot-scope
在 <template> 上使用特殊的 slot-scope attribute,可以接收传递给插槽的 prop (把这里提到过的 <slot-example> 组件作为示例):
<slot-example>
<template slot="default" slot-scope="slotProps">
{{ slotProps.msg }}
</template>
</slot-example>
这里的 slot-scope 声明了被接收的 prop 对象会作为 slotProps 变量存在于 <template> 作用域中。你可以像命名 JavaScript 函数参数一样随意命名 slotProps。
这里的 slot="default" 可以被忽略为隐性写法:
<slot-example>
<span slot-scope="slotProps">
{{ slotProps.msg }}
</span>
</slot-example>
```
slot-scope 的值可以接收任何有效的可以出现在函数定义的参数位置上的 JavaScript 表达式。这意味着在支持的环境下 (单文件组件或现代浏览器),你也可以在表达式中使用 ES2015 解构,如下:.
<slot-example>
<span slot-scope="{ msg }">
{{ msg }}
</span>
</slot-example>
使用这里描述过的 <todo-list> 作为示例,与它等价的使用 slot-scope 的代码是:
```
<todo-list v-bind:todos="todos">
<template slot="todo" slot-scope="{ todo }">
<span v-if="todo.isComplete">✓</span>
{{ todo.text }}
</template>
</todo-list>
<todo-list v-bind:todos="todos">
<template v-slot:todo="{ todo }">
<span v-if="todo.isComplete">✓</span>
{{ todo.text }}
</template>
</todo-list>
```
此博客参考于官网:链接: [Vue.js插槽](https://cn.vuejs.org/v2/guide/components-slots.html).