什么插槽
官网说明:
在 2.6.0
中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot
指令)。它取代了 slot
和 slot-scope
这两个目前已被废弃但未被移除且仍在文档中的特性。新语法的由来可查阅这份 RFC。
简单的概念:插槽,也就是
slot
,是组件的一块HTML
模板,这块模板显示不显示、以及怎样显示由父组件来决定。slot
最核心的是显示不显示
和怎样显示
。非插槽模板
html
模板:
指的是div、span、ul、table
这些,非插槽模板的显示与隐藏以及怎样显示由插件自身控制;插槽模板
slot
它是一个空壳子,因为它显示与隐藏
以及最后用什么样的html模板显示
由父组件控制。但是插槽显示的位置
确由子组件自身
决定,slot
写在组件template
的哪块,父组件传过来的模板将来就显示在哪块。
单个插槽|默认插槽 | 匿名插槽
概念:
单个插槽是vue
的官方叫法,是默认插槽,也是匿名插槽。因为它不用设置name
属性。
单个插槽, 一个组件中只能有一个该类插槽。具名插槽就可以有很多个,只要名字(name
属性)不同就可以了。样例:
如果父模板传递了值过去,则插槽占位处显示父组件传递过去的值,否则默认为子组件插槽的内容,一般情况为空。
父模板
<div class="parent">
<h3>这里是父组件</h3>
<alert-box>有bug发生</alert-box>
<alert-box>有一个警告</alert-box>
<alert-box></alert-box>
</div>
子组件
Vue.component('alert-box', {
template: `
<div> <strong>ERROR:</strong>
<slot>子组件插槽默认内容</slot>
</div>
`
});
展示结果:
ERROR: 有bug发生
ERROR: 有一个警告
ERROR: 子组件插槽默认内容
<template>
<div class="parent">
<h3>这里是父组件</h3>
<child>
<h4>这里是子组件中插槽占位处要展示的内容</h4>
<div class="tmpl">
<span>菜单1</span>
<span>菜单2</span>
</div>
</child>
</div>
</template>
子组件
<template>
<div class="child">
<h3>这里是子组件</h3>
<slot></slot>
</div>
</template>
具名插槽
- 概念:
插槽加了name
属性,具名插槽可以在一个
组件中出现N次
。出现在不同的位置
。总之,存在多个具名插槽的情况下,只需要找准该slot="name"
下的slot
即可,将对应的父组件内容传递到子组件slot占位处
。父组件通过html
模板上的slot
属性关联具名插槽。没有slot属性的html
模板默认关联匿名插槽。 - 样例:
父组件
<base-layout>
<p slot='header'>标题信息</p>
<p>主要内容1</p>
<p>主要内容2</p>
<p slot='footer'>底部信息</p>
</base-layout>
子组件:
Vue.component('base-layout', {
template: `
<div>
有name的插槽可以在该组件中存在多次
<header><slot name='header'></slot></header>
<main> <slot></slot></main>
<footer><slot name='footer'></slot></footer>
</div>
`
});
展示结果:
标题信息
主要内容1
主要内容2
底部信息
作用域插槽 | 带数据的插槽
作用域插槽:在slot
上面绑定数据。自 2.6.0 起有所更新。已废弃的使用 slot-scope
特性的语法。官网介绍新版
slot-scope
声明了被接收的prop
对象会作为 slotProps
变量存在于 <template>
作用域中。你可以像命名JavaScript
函数参数一样随意命名 slotProps
<fruit-list :list='list'>
<template slot-scope='slotProps'>
<strong v-if='slotProps.info.id==3' class="current">
{{slotProps.info.name}}
</strong>
</template>
</fruit-list>
Vue.component('fruit-list', {
props: ['list'],
template: `
<div>
<li :key='item.id' v-for='item in list'>
<slot :info='item'>{{item.name}}</slot>
</li>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
list: [{
id: '1',
name: 'apple'
}, {
id: '2',
name: 'orange'
}, {
id: '3',
name: 'banana'
}
]
}
});
结果:
apple
orange
banana
2.6.0+官网写法
将包含所有插槽prop
的对象命名为 slotProps
名字任意取。
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:
<!-- 无效,会导致警告 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
<template v-slot:other="otherSlotProps">
slotProps is NOT available here
</template>
</current-user>
- 只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template> 的语法:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user
解构插槽Prop
- 作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里,这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。
function (slotProps) {
// 插槽内容
}
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
重命名
<current-user v-slot="{ user: person }">
{{ person.firstName }}
</current-user>
具名插槽
跟 v-on
和 v-bind
一样,v-slot
也有缩写,即把参数之前的所有内容(v-slot:)
替换为字符#
。例如v-slot:header
可以被重写为 #header
<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>
- 然而,和其它指令一样,该缩写只在其有参数的时候才可用。这意味着以下语法是无效的:
<!-- 这样会触发一个警告 -->
<current-user #="{ user }">
{{ user.firstName }}
</current-user>
- 如果你希望使用缩写的话,你必须始终以明确插槽名取而代之:
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>