VUE——组件(三)使用slot分发内容
当需要让组件组合使用,混合父组件的内容与子组件的模板时,就会用到sloat,这个过程叫做内容分发。
props传递数据,events触发事件,sloat分发内容,就构成了vue组件的3个API来源。
一、slot的用法
单个slot
在子组件内使用特殊的<slot>元素就可以为这个子组件开启一个slot(插槽),在父组件模板里,插入在子组件标签内的所有内容将替代子组件的<slot>标签及它的内容。
<div id="app">
<child-component>
<p>这是分发内容</p>
<p>更多的分发内容</p>
</child-component>
</div>
<script type="text/javascript">
Vue.component('child-component',{
props:{},
template:'<div>\
<slot>\
<p>如果父组件没有插入内容,我将作为默认出现</p>\
</slot>\
</div>'
})
var app = new Vue({
el: '#app',
data: { },
methods:{}
})
</script>
子组件child-component 模板内定义了一个<slot>元素,并且用一个<p>作为默认的内容,在父组件没有使用<slot>时,会渲染这段默认的文本,如果父组件写入了<slot>,那父组件的slot会替换整个子组件的<slot>
最终渲染结果为:
<div id="app">
<div>
<p>这是分发内容</p>
<p>更多的分发内容</p>
</div>
</div>
注意:子组件内的备用内容,它的作用域是子组件本身
具名slot
给<slot>指定一个name后可以分发多个内容,具名<slot>可以和单个<slot>共存
<div id="app">
<child-component>
<h2 slot="header">标题</h2>
<p>正文内容</p>
<p>更多正文内容</p>
<div slot="footer">底部信息</div>
</child-component>
</div>
<script type="text/javascript">
Vue.component('child-component',{
props:{},
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',
data: { },
methods:{}
})
</script>
子组件内声明了多个<slot>元素,其中<div class="min">内的<slot>没有使用name特性,它将作为默认的<slot>出现,父组件没有使用<slot>特性的元素与内容将出现在这里
作用域插槽
作用域插槽是一种特殊的<slot>,使用一个可复用的模板替换已渲染的元素。
<div id="app">
<child-component>
<template scope="props"><!--props将数据传到插槽 临时变量--><!--通过临时变量props访问来自子组件插槽的数据msg-->
<p>来自父组件的内容</p>
<p>{{props.msg}}</p>
</template>
</child-component>
</div>
<script type="text/javascript">
Vue.component('child-component',{
props:{},
template:'<div class="container">\
<slot msg="来自子组件的内容"></slot>\
</div>'
})
var app = new Vue({
el: '#app',
data: { },
methods:{}
})
</script>
最终渲染结果为
<div id="app">
<div class="container">
<p>来自父组件的内容</p>
<p>来自子组件的内容</p>
</div>
</div>
作用域插槽更具代表性的是列表组件,允许组件自定义列表每一项如何渲染
<div id="app">
<my-list :books="books">
<template slot="book" scope="props"><!--作用域插槽也可以是具名slot-->
<li>{{props.bookName}}</li>
</template>
</my-list>
</div>
<script type="text/javascript">
Vue.component('my-list', {
props: {
books:{
type:Array,
default:function(){
return []
}
}
},
template: '<ul>\
<slot name="book"\
v-for="item in books"\
:book-name="item.name"\
></slot>\
</ul'
})
var app = new Vue({
el: '#app',
data: {
books:[
{name:'《我爸爸》'},
{name:'《我妈妈》'},
{name:'《我最爱我自己》'}
]
},
methods: {}
})
</script>
作用域插槽的使用场景就是既可以复用子组件的slot有可以使slot内容不一致。
访问slot
Vue2中提供了$slots来访问分发内容
<div id="app">
<child-component>
<h2 slot="header">标题</h2>
<p>正文内容</p>
<p>更多正文内容</p>
<div slot="footer">底部信息</div>
</child-component>
</div>
<script type="text/javascript">
Vue.component('child-component',{
props:{},
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>',
mounted:function(){//el挂载到实例上时调用,一般我们的第一个业务逻辑会写在这里
var header= this.$slots.header,
main=this.$slots.default,
footer=this.$slots.footer;
console.log(header,main,footer)
}
})
var app = new Vue({
el: '#app',
data: { },
methods:{}
})
</script>
通过slots可以访问某个具名的slot,this.$slots.default包括来所有没有具名的slot
浙公网安备 33010602011771号