指南
基础
- 安装
- 介绍
- Vue 实例
- 模板语法
- 计算属性和侦听器
- 类和样式绑定
- 条件渲染
- 列表渲染
- 事件处理
- 表单输入绑定
- 组件基础
组件深入
- 组件注册
- Props
- 自定义事件
- 插槽
- 动态和异步组件
- 处理边缘情况
过渡和动画
- 进入/离开和列表过渡
- 状态过渡
可重用性和组合
- 混入
- 自定义指令
- 渲染函数和 JSX
- 插件
- 过滤器
工具
- 单文件组件
- 测试
- TypeScript 支持
- 生产部署
扩展
- 路由
- 状态管理
- 服务器端渲染
- 安全
内部机制
- 深入响应性
迁移
- 从 Vue 1.x 迁移
- 从 Vue Router 0.7.x 迁移
- 从 Vuex 0.6.x 迁移到 1.0
- 迁移到 Vue 2.7
元数据
- 与其他框架的比较
- 加入 Vue.js 社区!
- 认识团队
插槽
本页假设您已经阅读了 组件基础。如果您是组件新手,请先阅读它。
在 2.6.0 中,我们引入了一种新的统一语法 (
v-slot
指令) 用于命名插槽和作用域插槽。它取代了slot
和slot-scope
属性,这些属性现在已弃用,但尚未删除,并且仍然在 此处 文档化。引入新语法的理由在以下 RFC 中描述。
插槽内容
Vue 实现了一个内容分发 API,灵感来自 Web Components 规范草案,使用 <slot>
元素作为内容分发出口。
这允许您像这样组合组件
|
然后在 <navigation-link>
的模板中,您可能会有
|
当组件渲染时,<slot></slot>
将被替换为“您的个人资料”。插槽可以包含任何模板代码,包括 HTML
|
甚至其他组件
|
如果 <navigation-link>
的模板没有包含 <slot>
元素,则其开始和结束标签之间提供的任何内容都将被丢弃。
编译范围
当您想在插槽中使用数据时,例如在
|
该插槽可以访问与模板其余部分相同的实例属性(即相同的“范围”)。插槽无法访问 <navigation-link>
的范围。例如,尝试访问 url
将不起作用
|
作为一项规则,请记住
父模板中的所有内容都在父范围中编译;子模板中的所有内容都在子范围中编译。
回退内容
在某些情况下,为插槽指定回退(即默认)内容很有用,只有在没有提供内容时才渲染。例如,在 <submit-button>
组件中
|
我们可能希望“提交”文本在大多数情况下渲染在 <button>
中。为了使“提交”成为回退内容,我们可以将其放置在 <slot>
标签之间
|
现在,当我们在父组件中使用 <submit-button>
时,不为插槽提供任何内容
|
将渲染回退内容“提交”
|
但是,如果我们提供内容
|
那么将渲染提供的內容而不是回退内容
|
命名插槽
在 2.6.0+ 中更新。 请参阅此处 以了解使用
slot
属性的弃用语法。
有时,拥有多个插槽很有用。例如,在具有以下模板的 <base-layout>
组件中
|
对于这些情况,<slot>
元素有一个特殊属性 name
,它可以用来定义额外的插槽
|
没有 name
的 <slot>
出口隐式地具有名称“default”。
要向命名插槽提供内容,我们可以在 <template>
上使用 v-slot
指令,将插槽的名称作为 v-slot
的参数提供
|
现在,<template>
元素中的所有内容都将传递到相应的插槽。任何没有用 v-slot
包裹在 <template>
中的内容都被认为是用于默认插槽。
但是,如果您希望明确,您仍然可以将默认插槽内容包裹在 <template>
中
|
无论哪种方式,渲染的 HTML 将是
|
请注意,v-slot
只能添加到 <template>
(有一个例外),与弃用的 slot
属性 不同。
作用域插槽
在 2.6.0+ 中更新。 请参阅此处 以了解使用
slot-scope
属性的弃用语法。
有时,让插槽内容访问仅在子组件中可用的数据很有用。例如,想象一个具有以下模板的 <current-user>
组件
|
我们可能希望替换此回退内容以显示用户的姓,而不是名,如下所示
|
但是,这将不起作用,因为只有 <current-user>
组件可以访问 user
,而我们提供的内容是在父级中渲染的。
为了使 user
可用于父级中的插槽内容,我们可以将 user
作为属性绑定到 <slot>
元素
|
绑定到 <slot>
元素的属性称为插槽 props。现在,在父级范围中,我们可以使用带有值的 v-slot
来定义我们已提供的插槽 props 的名称
|
在此示例中,我们选择将包含所有插槽 props 的对象命名为 slotProps
,但您可以使用任何您喜欢的名称。
仅默认插槽的简写语法
在上述情况下,当仅默认插槽提供内容时,组件的标签可以用作插槽的模板。这使我们能够直接在组件上使用 v-slot
|
这可以进一步缩短。就像未指定的内容被认为是用于默认插槽一样,没有参数的 v-slot
被认为是指默认插槽
|
请注意,默认插槽的简写语法不能与命名插槽混合使用,因为它会导致范围歧义
|
只要有多个插槽,就对所有插槽使用完整的基于 <template>
的语法
|
解构插槽 Props
在内部,作用域插槽通过将您的插槽内容包装在一个传递单个参数的函数中来工作
|
这意味着 v-slot
的值实际上可以接受任何有效的 JavaScript 表达式,该表达式可以出现在函数定义的参数位置。因此,在支持的环境(单文件组件 或 现代浏览器)中,您也可以使用 ES2015 解构 来提取特定的插槽 props,如下所示
|
这可以使模板更加简洁,尤其是在插槽提供许多 props 时。它还打开了其他可能性,例如重命名 props,例如将 user
重命名为 person
|
您甚至可以定义回退,在插槽 prop 未定义的情况下使用
|
动态插槽名称
在 2.6.0+ 中新增
动态指令参数 也适用于 v-slot
,允许定义动态插槽名称
|
命名插槽简写
在 2.6.0+ 中新增
与 v-on
和 v-bind
类似,v-slot
也有一个简写,用特殊符号 #
替换参数之前的部分 (v-slot:
)。例如,v-slot:header
可以改写为 #header
|
但是,就像其他指令一样,简写仅在提供参数时才可用。这意味着以下语法无效
|
相反,如果您希望使用简写,则必须始终指定插槽的名称
|
其他示例
插槽 props 使我们能够将插槽变成可重用的模板,这些模板可以根据输入 props 渲染不同的内容。 当您正在设计一个可重用组件来封装数据逻辑,同时允许使用它的父组件自定义其布局的一部分时,这最有用。
例如,我们正在实现一个<todo-list>
组件,它包含列表的布局和过滤逻辑。
|
与其为每个待办事项硬编码内容,我们可以让父组件通过将每个待办事项都设为一个插槽来控制,然后将todo
绑定为插槽属性。
|
现在,当我们使用<todo-list>
组件时,我们可以选择性地为待办事项定义一个替代的<template>
,但可以访问来自子组件的数据。
|
然而,即使这样也仅仅触及了作用域插槽功能的皮毛。为了获得作用域插槽使用的真实、强大的示例,我们建议浏览诸如Vue Virtual Scroller、Vue Promised和Portal Vue等库。
已弃用语法
v-slot
指令是在 Vue 2.6.0 中引入的,它提供了一个改进的、替代的 API,用于仍然支持的slot
和slot-scope
属性。引入v-slot
的完整理由在RFC中进行了描述。slot
和slot-scope
属性将在所有未来的 2.x 版本中继续得到支持,但它们已被正式弃用,最终将在 Vue 3 中删除。
使用slot
属性的命名插槽
已弃用在 2.6.0+ 中。有关新的、推荐的语法,请参见此处。
要从父组件传递内容到命名插槽,请在<template>
上使用特殊的slot
属性(使用此处描述的<base-layout>
组件作为示例)。
|
或者,slot
属性也可以直接用于普通元素。
|
仍然可以有一个未命名的插槽,它是默认插槽,用作任何不匹配内容的占位符。在上面的两个示例中,渲染的 HTML 将是
|
使用slot-scope
属性的作用域插槽
已弃用在 2.6.0+ 中。有关新的、推荐的语法,请参见此处。
要接收传递到插槽的 props,父组件可以使用带有slot-scope
属性的<template>
(使用此处描述的<slot-example>
作为示例)。
|
此处,slot-scope
将接收到的 props 对象声明为slotProps
变量,并在<template>
作用域内使其可用。您可以像在 JavaScript 中命名函数参数一样,将slotProps
命名为任何您喜欢的名称。
此处,slot="default"
可以省略,因为它隐含的。
|
slot-scope
属性也可以直接用于非<template>
元素(包括组件)。
|
slot-scope
的值可以接受任何有效的 JavaScript 表达式,该表达式可以出现在函数定义的参数位置。这意味着在支持的环境(单文件组件或现代浏览器)中,您也可以使用ES2015 解构在表达式中,如下所示。
|
使用此处描述的<todo-list>
作为示例,以下是使用slot-scope
的等效用法。
|