九、在Vue中使用插槽
<body>
<div id="root">
<child></child>
</div>
<script>
Vue.component('child',{
template:'<div><p>hello</p></div>'
})
var vm = new Vue({
el:"#root"
})
</script>
</body>
页面显示如下:
图片.png
那么什么时候会用到插槽呢?
假设现在有一个需求:子组件除了展示P标签外,还要展示一段内容,但是这个内容不是子组件所决定的,而是父组件传递过来的。
按照以前学的内容,从父组件传递给子组件,需要通过属性的形式来传递。
修改后如下:
<body>
<div id="root">
<child content='<p>Dell</p>'></child>
</div>
<script>
Vue.component('child',{
props:['content'],
template:`<div>
<p>hello</p>
<div v-html="this.content"></div>
</div>`
})
var vm = new Vue({
el:"#root"
})
</script>
</body>
其中子组件中template用了es6的语法``,如果用以前的语法也可以:
template:'<div><p>hello</p><div v-html="this.content"></div></div>'
这样是可行的,但是会有一个问题,如果父组件向子组件传值传的比较少,这样做是没问题的;但是当要传的内容很多的时候,代码就会变得很难阅读。
所以当子组件有一部分内容是根据父组件传递过来的DOM进行显示的时候,这时候就可以使用—插槽slot。
改变后的语法如下:
<body>
<div id="root">
<child>
<p>Dell</p>
</child>
</div>
<script>
Vue.component('child',{
template:`<div>
<p>Hello</p>
<slot></slot>
</div>`
})
var vm = new Vue({
el:"#root"
})
</script>
</body>
这种语法就像在使用的child标签中插入了内容(p标签),故叫插槽。
往子组件中插入了内容,那么子组件就有办法用到传递过来的内容,这时就使用了Vue中的内置语法—slot。slot显示的就是父组件中往子组件插入的p标签。
当然插槽还有一些别的特性。
1、slot标签内可以定义默认值:当在slot标签内写上别的内容(比如“默认内容”),且父组件中子组件没有插入插槽,这个时候slot中的内容(“默认内容”)就会显示出来。
代码如下:
<body>
<div id="root">
<child>
</child>
</div>
<script>
Vue.component('child',{
template:`<div>
<p>Hello</p>
<slot>默认内容</slot>
</div>`
})
var vm = new Vue({
el:"#root"
})
</script>
</body>
网页显示如下:
图片.png
2、有选择的使用slot——具名插槽
先举个例子:
<body>
<div id="root">
<body-content></body-content>
</div>
<script>
Vue.component('body-content',{
template:`<div>
<div class='content'>content</div>
</div>`
})
var vm = new Vue({
el:"#root"
})
</script>
</body>
子组件中的内容会显示在上面的div标签上,但是如果我的需求是整个数据不只是单单由子组件的内容决定的,还由其他的内容决定(比如来一个头部数据和一个尾部数据),这就可以用到了插槽。
数据如下:
<body>
<div id="root">
<body-content>
<div class="header">header</div>
<div class="footer">footer</div>
</body-content>
</div>
<script>
Vue.component('body-content',{
template:`<div>
<slot></slot>
<div class='content'>content</div>
<slot></slot>
</div>`
})
var vm = new Vue({
el:"#root"
})
</script>
</body>
网页显示如下:
图片.png
这个显示并不是我想要的,因为我想要的顺序是头部-content-尾部。但是这个显示的重复了。
这时就需要来给slot取名来避免这个问题。
修改代码如下:
<body>
<div id="root">
<body-content>
<div class="header" slot='header'>header</div>
<div class="footer" slot='footer'>footer</div>
</body-content>
</div>
<script>
Vue.component('body-content',{
template:`<div>
<slot name='header'></slot>
<div class='content'>content</div>
<slot name='footer'></slot>
</div>`
})
var vm = new Vue({
el:"#root"
})
</script>
</body>
这个子组件需要从外部接收两个插入的内容,一部分的内容叫header,一部分的内容叫footer,而在父组件调用子组件的时候,插入了两个插槽,一个是插槽header,另一个是插槽footer。
这种写法,可以在调用子组件的时候,一次性传入多个区域的DOM结构;在子组件中,通过具名插槽,分别使用不同的DOM结构,方便做复杂的调用。
插槽和具名插槽的区别:插槽只可以有一个,而具名插槽可以有多个
当然。具名插槽也可以有默认内容。