插槽目的:传给子许多标签dom啥的,让子去显示
引入:
<div id="app">
<child content="<div><p>dell</p></div>"></child>
</div>
<script>
var child = {
props: ['content'],
// template: `<div><p>hello</p>{{content}}</div>`,
// hello <div><p>dell</p></div>
template: `<div><p>hello</p><div v-html="content"></div></div>`,
// hello dell 有问题 多个div
// template: `<div><p>hello</p><template v-html="content"></template></div>`,
// 不行 有问题 不能显示
data() {
return {
}
},
}
var app = new Vue({
el: '#app',
components: { child }
})
</script>
- 往子传内容,如果只用属性传递,传很长的标签内容会造冗余,不易读
- 会多个div
slot定义
slot就是可以在自定义组件标签中写内容插入进去
需要向一个组件传递内容
<alert-box>
Something bad happened.
</alert-box>
幸好,Vue 自定义的 <slot> 元素让这变得非常简单:
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
如你所见,我们只要在需要的地方加入插槽就行了——就这么简单!
插槽
用子组件的时候,往里插入内容叫插槽。子用到时,怎么使用插槽中的内容:<slot>
要插入的许多标签放在<child>中,这里面叫插槽。slot标签放在子template中。这时slot的内容实质上就是上面子插进来的内容,slot代表插槽里的内容 。
想实现:子组件的很多内容不是自己决定的,而是由外部决定的
没有包含一个 <slot> 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。
<slot>默认内容</slot>
<div id="app">
<child>
<!-- <p>dell</p> -->
<div class="header">header</div>
<div class="footer">footer</div>
</child>
</div>
<script>
var child = {
// template: `<div><p>hello</p><slot></slot></div>`,
// hello dell
// template: `<div><p>hello</p><slot>默认内容</slot></div>`,
// hello 默认内容
// template: `<div><p>hello</p><slot><h1>12</h1></slot></div>`,
// hello 12 默认值是12
// 想实现:子组件的很多内容不是自己决定的,而是由外部决定的
template: `<div>
<slot></slot>
<div class='content'>content</div>
<slot></slot>
</div>`,
// slot代表插槽里的内容
// header
// footer
// content
// header
// footer
}
var app = new Vue({
el: '#app',
components: { child }
})
</script>
具名插槽
<div id="app">
<child>
<div class="header" slot="header">header</div>
<div class="footer" slot="footer">footer</div>
</child>
</div>
<script>
var child = {
template: `<div>
<slot name="header"></slot>
<div class='content'>content</div>
<slot name="footer"></slot>
</div>`,
}
var app = new Vue({
el: '#app',
components: { child }
})
</script>
具名插槽的默认值
<div id="app">
<child>
<div class="footer" slot="footer">footer</div>
</child>
</div>
<script>
var child = {
template: `<div>
<slot name="header">default header</slot>
<slot name="header1"><h1>default header h1</h1></slot>
<div class='content'>content</div>
<slot name="footer"></slot>
</div>`,
}
var app = new Vue({
el: '#app',
components: { child }
})
</script>
作用域插槽
子组件中有个数组数据,可以循环显示
需求:子组件child在多个地方用,希望不同地方调用时,列表怎么循环,列表的样式不是child控制的,而是外部告诉我们组件的每一项应该如何渲染。
使用场景:子组件循环,他的某一部分的dom结构应该由外部传进来。(子组件传数据,父接收数据template slot-scope,决定如何展示)
<div id="app">
<child></child>
</div>
<script>
var child = {
template: `<div>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>`,
data() {
return {
list: [1, 2, 3, 4]
}
}
}
var app = new Vue({
el: '#app',
components: { child }
})
</script>
<div id="app">
<child>
<!-- 调用child时,内部怎么循环展示,子组件slot内部不关心怎么显示,由外部告诉组件的每一项如何渲染 -->
<!-- 套个template是个固定的写法 -->
<!-- 这里props这个值可以随便定义,当子组件用slot时,会往slot里传个item数据。上面用child时,就可以用item数据,item就放在props中 -->
<!-- 由这里传递对应的摸板 -->
<!-- 父调子时,给子传了个插槽。传了个作用域插槽,作用域插槽必须是template开头结尾 -->
<!-- 插槽要声明从子组件接收的数据都放在哪,这里是props。
还要告诉子组件一个摸板的信息。即接收到的数据该如何展示。 -->
<template slot-scope="props">
<!-- <li>{{props.item}}</li> -->
<h1>{{props.item}}</h1>
</template>
</child>
</div>
<script>
var child = {
template: `<div>
<ul>
<slot v-for="item in list" :item=item></slot>
</ul>
</div>`,
data() {
return {
list: [1, 2, 3, 4]
}
}
}
var app = new Vue({
el: '#app',
components: { child }
})
</script>
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的
你想想那个插槽,其实就是把东西拿去子组件去
所以作用域插槽里面的数据就是子组件的数据