什么是slot
当需要让组件组合使用,混合父组件的内容与子组件的模板时,就回用到slot,这个过程叫内容分发
props传递数据,events触发事件和slot内容分发构成了vue组件的3个api来源
如下例:
<child-component>
{{message}}
</child-component>
这里的message就是一个slot,但是它绑定的是父组件的数据,而不是<child-component>
的数据
父组件模板的内容是在父组件作用域内编译,
子组件模板的内容是在子组件作用域内编译
如下例:
<div id="app">
<child-component v-show="showChild"></child-component>
</div>
<script>
Vue.component('child-component',{
template: '<div>子组件</div>'
});
var app = new Vue({
el: '#app',
data: {
showChild: true
}
})
</script>
这里showChild绑定的是父组件的数据
如果要再子组件上绑定就要用
则应该是
<div id="app">
<child-component></child-component>
</div>
<script>
Vue.component('child-component',{
template: '<div v-show="showChild">子组件</div>'
data: function(){
return {
showChild: true
}
}
});
var app = new Vue({
el: '#app',
})
</script>
slot分发内容,作用域是在父组件上的
单个slot
在子组件使用元素就为这个子组件开启了插槽,
在父组件模板中,插入在子组件标签内的所有内容将替代子组件标签及它的内容
示例代码如下:
<div id="app">
<child-component>
<p>分发内容</p>
</child-component>
</div>
<script>
Vue.component('child-component', {
template: ‘\
<div>\
<slot>\
<p>如果父组件没有插入内容,我将作为默认出现</p>\
</slot>
})
var app = new Vue({
el: '#app'
})
</script>
如果父组件没有使用slot,则ui渲染这段默认文本,如果写入slot,那会替换整个slot
注意子组件slot内的备用内容,其作用域是子组件本身
具名slot
给slot添加name后可以分发多个内容
具名slot可以和单个slot共存
<div id="app">
<child-component>
<h2 slot="header">标题</slot>
<p>正文内容</p>
<div slot="footer">底部信息</slot>
</child-component>
</div>
<script>
Vue.component('child-component',{
template: '\
<div class="container">\
<div class="header">\
<slot name="header"></slot>\
</div>\
<div class="main">\
<slot></slot>\
</div>\
<div class="footer">\
<slot name="footer"></slot>\
</div>\
</div>'
}
var app = new Vue({
el: '#app'
})
</script>
最终渲染结果是
<div id="app">
<div class="container">
<div class="header">
<h2>标题</h2>
</div>
<div class="main">
<p>正文内容</p>
</div>
<div class="footer">
<div>底部信息</div>
</div>
</div>
</div>
注意:如果没有指定默认的匿名slot,父组件内多余的内容片段都将被抛弃
作用域插槽
作用域插槽,使用一个可以复用的模板替换已渲染元素。
见下例:
<div id="app">
<child-component>
<template scope="props">
<p>来自父组件的内容</p>
<p>{{props.msg}}</p>
</template>
</child-component>
</div>
<script>
Vue.component('child-component', {
template: '\
<div class="container">\
<slot msg="来自子组件的内容"></slot>
</div>'
});
var app = new Vue({
el: '#app'
})
</script>
注意子组件 slot上有类似props传递数据给组件的写法msg="…",将数据传递给父组件。在父组件中props只是一个临时变量,就像v-for="item in items"里的item一样。template内可以通过临时变量props访问来自子组件插槽的数据msg
渲染后的结果是:
<div id="app">
<div class="container">
<p>来自父组件的内容</p>
<p>来自子组件的内容</p>
</div>
</div>
作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项
作用域插槽的使用场景就是既可以复用子组件的slot,又可以使slot内容不一致。
访问slot
使用$slot
可以访问具名slot,this.$slot.default
包括了所有没有被包含在具名slot中的节点