vm.$slots
是一个对象,键名是所有具名slot
的名称,加上一个default
,而键值则是一个存放VNode
节点的数组。
官网上提供的解释如下:
用来访问被
slot
分发的内容。每个具名slot
有其相应的属性
(例如:slot="foo"
中的内容将会在vm.$slots.foo
中被找到)
default 属性包括了所有没有被包含在具名 slot 中的节点。
示例如下:
<blog-post>
<h1 slot="header">
我属于header
</h1>
<h1 slot="header">
我也属于header
</h1>
<p>
我谁都不属于
</p>
<p slot="footer">
我属于footer
</p>
<p>
谁来认领我
</p>
</blog-post>
在blog-post
标签里,元素们被这样的设置:
- 属于名称为
header
的slot
的有2个<h1>
- 属于名称为
footer
的slot
的有1个<p>
- 属于不具名
slot
(会归到default
里)的有2个<p>
尝试查看blog-post
组件的$slots
,得到结果如下:
可以看到:
-
header
对应一个长为2的数组,就是刚才那2个<h1>
对应的VNode
节点。 -
footer
对应一个长为1的数组,就是刚才那1个<p>
对应的VNode
节点。 -
default
对应一个长为6的数组,其中有4个是空的VNode
节点(产生的原因尚不清楚),2个是刚才没有指定slot
属性的<p>
对应的VNode
节点。
如果像下面这样,指定了render函数的话,就可以手动创建出html标签。
Vue.component('blog-post', {
render: function (createElement) {
var header = this.$slots.header
var body = this.$slots.default
var footer = this.$slots.footer
return createElement('div', [
createElement('header', header),
createElement('main', body),
createElement('footer', footer)
])
}
})
createElement(html标签名, VNode节点数组)
会编译出一个指定的html标签,然后把VNode
节点数组里非空的VNode
节点编译回原来的html内容。其结果就相当于把原来的那些<blog-post>
标签之间的内容根据它们的slot
属性,放进了指定的标签里。
刚刚的例子里,最终编译出的html
结构如下: