指南
基础概要
- 安装
- 介绍
- Vue 实例
- 模板语法
- computed 属性和 watcher
- class 和 style 绑定
- 根据条件进行渲染
- 列表渲染
- 事件处理
- 表单 input 绑定
- 组件基础
过渡 & 动画
- 进入、离开和列表的过渡
深入组件
- 组件注册
- props
- 自定义事件
- slot
- 动态组件和异步组件
- Handling Edge Cases
- 状态间的过渡
可重用 & 合成
- mixin
- 自定义指令
- render 函数 & jsx
- 插件
- 过滤器
工具
- 生产环境部署
- 单文件组件
- 单元测试
- TypeScript 支持
扩展升级
- 路由
- 状态管理
- 服务端渲染
内部原理
- 深入响应式原理
升级迁移
- 从 Vue 1.x 迁移
- 从 Vue Router 0.7.x 迁移
- 从 Vuex 0.6.x 迁移到 1.0
其他更多
- 对比其他框架
- 加入 Vue.js 社区
- 认识团队
slot
本页面会假定你已经阅读过 组件基础。如果你还不熟悉组件,请先阅读组件基础后再阅读本页面。
插槽内容(slot content)
Vue 基于现有 Web Components 规范草案,实现一个 内容分发(content distribution) API 模型,使用 <slot>
元素,作为内容分发的位置。
内容分发机制,可以帮助你以如下方式构成组件:
<navigation-link url="/profile"> |
然后,在 <navigation-link>
模板中,可能是:
<a |
在组件渲染时,<slot>
元素就会被替换为 “Your Profile”。在 slot 位置,可以包含任何模板代码,也包括 HTML:
<navigation-link url="/profile"> |
甚至,slot 位置也能包含其他组件:
<navigation-link url="/profile"> |
如果 <navigation-link>
完全没有 <slot>
元素,则 slot 位置传递的所有内容都会被直接丢弃。
命名插槽(named slot)
在某些场景中,需要用到多个插槽。例如,在一个假想的 base-layout
组件中,需要传入以下模板:
<div class="container"> |
对于这种场景,<slot>
元素有一个特殊的 name
特性,可以用于定义除默认插槽以外的多余插槽:
<div class="container"> |
为了给命名插槽提供内容,我们可以在父组件模板的 <template>
元素上使用 slot
特性(译注:这样可以将父组件模板中 slot 位置,和子组件 slot 元素产生关联,便于插槽内容对应传递):
<base-layout> |
或者,也可以对某个普通元素,直接使用 slot
特性:
<base-layout> |
还有一个未命名插槽(unnamed slot),这是默认插槽,它是用于放置所有不匹配内容的插槽位置。在以上这两个示例中,最终渲染的 HTML 是:
<div class="container"> |
默认插槽内容(default slot content)
在某些场景中,需要插槽预先提供默认内容。例如,一个 <submit-button>
组件,可能想要将按钮文本内容,默认地设置为 “Submit”,然而也允许用户传入 “Save”, “Upload” 或其他文本,来覆盖默认文本。
为了实现这个效果,我们可以在 <slot>
元素内部指定一个默认内容。
<button type="submit"> |
如果父组件模板中,向 slot 位置提供了内容,子组件 slot 元素的默认内容就会被替换。
编译时的作用域(compilation scope)
当你在 slot 内部想要使用当前作用域下的数据,例如:
<navigation-link url="/profile"> |
这些插槽内容,可以访问与插槽模板之外其余部分模板,完全相同的实例属性(也就是处于同一“作用域”)。然而插槽内容无法访问 <navigation-link>
组件内部的作用域。例如,试图访问传入此组件内部的 url
,就会无法正常运行。牢记准则:
父组件模板的内容,全部在父组件作用域内编译;子组件模板的内容,全部在子组件作用域内编译。
作用域插槽(scoped slots)
2.1.0+ 新增
在某些场景中,需要提供一个具有「可以访问组件内部数据的可复用插槽(reusable slot)」的组件。例如,一个简单的 <todo-list>
组件,可能包含如下模板:
<ul> |
但是在我们应用程序的某些部分中,我们想要将 todo items 中的每一项,都渲染为不同于 todo.text
的内容。这就是引入作用域插槽的原因。
为了实现此潜在功能,我们必须将 todo item 的内容,包裹到一个 <slot>
元素中,然后,将此 slot 内部所需的所有相关数据,都传递给它的上下文环境(context):在当前这个场景中,其相关数据为 todo
对象:
<ul> |
现在,在我们引用 <todo-list>
组件的位置,我们可以将 todo items 插槽内容稍作修改,定义为一个 <template>
,并且通过 slot-scope
特性访问子组件数据:
<todo-list v-bind:todos="todos"> |
在 2.5.0+,
slot-scope
不再局限于<template>
元素,而是可以在任何元素或任何组件中的插槽内容上使用。
解构 slot-scope
slot-scope
的值,实际上可以接收任何有效的 JavaScript 表达式,可以出现在函数定义中的参数所在位置。也就是说,在支持的环境中(在 单个文件组件 或在 现代浏览器),可以使用 ES2015 解构 来对表达式进行解构,就像这样:
<todo-list v-bind:todos="todos"> |
这是让作用域插槽用法,变得思路清晰的好方法。