普通插槽
<div id="app">
<child con="<p>hello</p>"></child>
</div>
<script>
Vue.component("child",{
props:["con"],
template:'<div v-html="this.con"></div>'
})
new Vue({
el:'#app'
})
</script>
这就是页面输出后的dom结构,如果我们不想要外层div,只想要<p>hello</p>
,我们想到把外层div改成template
Vue.component("child",{
props:["con"],
template:'<template v-html="this.con"></template>'
})
但这么写更糟糕,都不显示了,而且这还有个问题,如果父组件传过来的内容很多,比如:
<child con="<p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p><p>hello</p>"></child>
那这么写,代码很难去阅读。
所以这里要用slot插槽,它可以解决上述问题。下面就展示使用插槽怎么由父组件向子组件优雅的展示dom结构
<div id="app">
<child>
<p>hello</p>
</child>
</div>
<script>
Vue.component("child",{
template:`<div>
<slot></slot>
</div>`
})
new Vue({
el:'#app'
})
</script>
slot显示的就是父组件向子组件插入的这个p标签
最终页面显示hello,dom结构如下:
注意这里的模版是多行字符串,所以用的是反引号``不是单引号
slot也有一些新特性,比如默认值
<div id="app">
<child>
</child>
</div>
<script>
Vue.component("child",{
template:`<div>
<slot>默认内容</slot>
</div>`
})
new Vue({
el:'#app'
})
</script>
如果没有插槽,则会显示默认内容
具名插槽
<div id="app">
<child>
<p slot="header">header</p>
<p slot="content">content</p>
<p slot="footer">footer</p>
</child>
</div>
<script>
Vue.component("child",{
template:`<div>
<slot name="header">默认值</slot>
<slot name="content">默认值</slot>
<slot name="footer">默认值</slot>
</div>`
})
new Vue({
el:'#app'
})
</script>
页面显示如下:
dom结构如下:
多个插槽可以有自己的名字
<div id="solt">
<app-layout>
<p slot="footer">这个是footer</p>
<h1 slot="header">这个是header</h1>
<p>这个什么都没有,只是一个P标签A</p>
<p>这个什么都没有,只是另一个P标签B</p>
<p slot="footer">这个是footer</p>
<p>这个什么都没有,只是另一个P标签C</p>
</app-layout>
</div>
<script>
Vue.component("app-layout", {
template:`<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>`
})
new Vue({
el: "#solt"
});
</script>
页面显示如下:
说明:
1,具名插槽的渲染顺序,完全取决于模板,而不是取决于父组件中元素的顺序
2,子组件有没有名字的slot,那它指代的是父组件中所有没有名字的插槽
3,子组件有名字的slot,如果在父组件中有多个对应的,则显示多个
作用域插槽
<div id="app">
<child>
<template slot-scope="props">
<!--这里一定是template,slot-scope表示插槽作用域,这里不一定非要写props,也可以是别的名字-->
<li>{{props.item}}</li>
<!--这里的item对应的是下面子组件的:item-->
</template>
</child>
</div>
<script>
var child = {
data() {
return {
list: [1, 2, 3, 4, 5]
};
},
template:
'<div><ul><slot v-for="item of list" :item=item></slot></ul></div>' //这里不一定非要写:item,也可以是别的名字比如:con
};
var vm = new Vue({
el: "#app",
components: {
child
}
});
</script>
如果子组件在多处使用,子组件里面要显示的内容由调用他的父组件提供,可以用插槽。