看Vue文档整理笔记,便于自己学习
Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将
元素作为承载分发内容的出口。
它允许你像这样合成组件:
Your Profile 然后你在
的模板中可能会写为:
当组件渲染的时候,
将会被替换为“Your Profile”。插槽内可以包含任何模板代码,包括 HTML:
Your Profile 甚至其它的组件:
Your Profile 如果
没有包含一个
元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
当你想在一个插槽中使用数据时,例如:
Logged in as {{ user.name }} 该插槽跟模板的其它地方一样可以访问相同的实例属性 (也就是相同的“作用域”),而不能访问
的作用域。例如
url
是访问不到的:
Clicking here will send you to: {{ url }} 作为一条规则,请记住:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
为一个插槽设置具体的后备 (也就是默认的) 内容 ,可以将它放在
标签内
现在当我在一个父级组件中使用
并且不提供任何插槽内容时:
后备内容“Submit”将会被渲染:
但是如果我们提供内容:
Save 则这个提供的内容将会被渲染从而取代后备内容:
自 2.6.0 起有所更新。已废弃的使用
slot
特性的语法在这里。有时我们需要多个插槽。例如对于一个带有如下模板的
组件:
对于这样的情况,
元素有一个特殊的特性:
name
。这个特性可以用来定义额外的插槽:
一个不带
name
的出口会带有隐含的名字“default”。
在向具名插槽提供内容的时候,我们可以在一个
元素上使用
v-slot
指令,并以v-slot
的参数的形式提供其名称:
Here might be a page title
A paragraph for the main content.
And another one.
Here's some contact info
现在
元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有
v-slot
的中的内容都会被视为默认插槽的内容。
然而,如果你希望更明确一些,仍然可以在一个
中包裹默认插槽的内容:
Here might be a page title
A paragraph for the main content.
And another one.
Here's some contact info
任何一种写法都会渲染出:
Here might be a page title
A paragraph for the main content.
And another one.
注意
v-slot
只能添加在一个上 (只有一种例外情况),这一点和已经废弃的
slot
特性不同。
自 2.6.0 起有所更新。已废弃的使用
slot-scope
特性的语法在这里。有时让插槽内容能够访问子组件中才有的数据是很有用的。例如,设想一个带有如下模板的
组件:
{{ user.lastName }} 我们想让它的后备内容显示用户的名,以取代正常情况下用户的姓,如下:
{{ user.firstName }} 然而上述代码不会正常工作,因为只有
组件可以访问到
user
而我们提供的内容是在父级渲染的。为了让
user
在父级的插槽内容可用,我们可以将user
作为元素的一个特性绑定上去:
{{ user.lastName }} 绑定在
元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给
v-slot
带一个值来定义我们提供的插槽 prop 的名字:
{{ slotProps.user.firstName }} 在这个例子中,我们选择将包含所有插槽 prop 的对象命名为
slotProps
,但你也可以使用任意你喜欢的名字。独占默认插槽的缩写语法
在上述情况下,当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把
v-slot
直接用在组件上:
{{ slotProps.user.firstName }} 这种写法还可以更简单。就像假定未指明的内容对应默认插槽一样,不带参数的
v-slot
被假定对应默认插槽:
{{ slotProps.user.firstName }} 注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:
{{ slotProps.user.firstName }} slotProps is NOT available here 只要出现多个插槽,请始终为所有的插槽使用完整的基于
的语法:
{{ slotProps.user.firstName }} ... 解构插槽 Prop
作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:
function (slotProps) { // 插槽内容 }
这意味着
v-slot
的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop,如下:
{{ user.firstName }} 这样可以使模板更简洁,尤其是在该插槽提供了多个 prop 的时候。它同样开启了 prop 重命名等其它可能,例如将
user
重命名为person
:
{{ person.firstName }} 你甚至可以定义后备内容,用于插槽 prop 是 undefined 的情形:
{{ user.firstName }}
动态指令参数也可以用在
v-slot
上,来定义动态的插槽名:
...
(
v-slot:
) 替换为字符#
。例如v-slot:header
可以被重写为#header
:
Here might be a page title
A paragraph for the main content.
And another one.
Here's some contact info
然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:
{{ user.firstName }} 如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:
{{ user.firstName }}
插槽 prop 允许我们将插槽转换为可复用的模板,这些模板可以基于输入的 prop 渲染出不同的内容。这在设计封装数据逻辑同时允许父级组件自定义部分布局的可复用组件时是最有用的。
例如,我们要实现一个
组件,它是一个列表且包含布局和过滤逻辑:
- {{ todo.text }}
我们可以将每个 todo 作为父级组件的插槽,以此通过父级组件对其进行控制,然后将
todo
作为一个插槽 prop 进行绑定:
{{ todo.text }} 现在当我们使用
组件的时候,我们可以选择为 todo 定义一个不一样的
作为替代方案,并且可以从子组件获取数据:
✓ {{ todo.text }} 这只是作用域插槽用武之地的冰山一角。想了解更多现实生活中的作用域插槽的用法,我们推荐浏览诸如 Vue Virtual Scroller、Vue Promised 和 Portal Vue 等库。