一、引入
和 HTML 元素一样,我们经常需要向一个组件传递内容,但是这个时候十分不方便,比如下面的这种情况(父组件给子组件传递一个p标签)
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="root">
<child content='<p>我是父组件传递过来的</p>'></child>
</div>
<script>
//创建子组件
Vue.component('child', {
props: ['content'],
template: `<div>
<p>我是child</p>
<div>{{content}}</div>
</div>`
})
//创建vue实例对象
var vm = new Vue({
el: '#root'
})
</script>
</body>
</html>
这并不是我们想要的结果,这时候可以使用v-html对父组件传来的content进行转义
`<div>
<p>我是child</p>
<div v-html="this.content"></div>
</div>
得到期待的结果
但是我们现在有更好的选择方案,就是这篇帖子接下来讲的slot(插槽)。直白来说,就是像一个预留好的插槽,我们可以直接传递东西后,放在这个预留的位置.
二、slot使用案例以及简单用法
2.1对入门案例进行改进
(1)父组件对child组件传值,直接写在child组件中,包裹起来,不在写标签上。
<child>
<p>我是父组件传递过来的</p>
</child>
(2)child组件中留好位置,去接受
Vue.component('child', {
props: ['content'],
template: `<div>
<p>我是child</p>
<slot></slot>
</div>`
})
得到下面结果
2.2slot的默认值
slot可以有默认值,父组件没有传递时候,直接显示slot中内容。
结果如下
2.3父组件传递多个值给child时候
这个例子很常见啦,比如child中是从下到下的头、中、尾布局,而child中只写了尾,而头还有中都是外面父组件传进来的,我们怎么让传来的2个(头、中),放到对应的位置呢?
是按顺序吗?nonono,是给slot取名字,这样传的时候指定这个值传给那个slot,这样就欧克了,看下面代码。(可以给slot去掉name之后看看得到的结果有什么不同)
<body>
<div id="root">
<child>
<div class="header" slot="header">我是父组件的传过来的头</div>
<div class="center" slot="center">我是父组件的传过来的中间</div>
</child>
</div>
<script>
//创建子组件
Vue.component('child', {
props: ['content'],
template: `<div>
<slot name="header"></slot>
<slot name="center"></slot>
<p>我是child自己的尾部</p>
</div>`
})
//创建vue实例对象
var vm = new Vue({
el: '#root'
})
</script>
</body>
结果
三、作用域插槽
(1)场景,子组件只负责数据怎么得来的,而样式是外部调用时候决定的
原始代码如下
<body>
<div id="root">
<child>
</child>
</div>
<script>
//创建子组件
Vue.component('child', {
data() {
return {
list: ['php', 'java', 'c++', 'javascript']
}
},
template: `<div>
<ul>
<li v-for="item of list">{{item}}</li>
</ul>
</div>`
})
//创建vue实例对象
var vm = new Vue({
el: '#root'
})
</script>
</body>
结果如下
(2)开始改造
说明,其中template标签是固定写法,当子组件循环出来的item我们绑定到一个item属性上,然后在父组件中用slot-scope定义的属性中,包含有item属性,通过item属性拿到绑定到item属性上的item值。
<body>
<div id="root">
<child>
<template slot-scope="props">
<h1>
{{props.item}}
</h1>
</template>
</child>
</div>
<script>
//创建子组件
Vue.component('child', {
data() {
return {
list: ['php', 'java', 'c++', 'javascript']
}
},
template: `<div>
<ul>
<slot v-for="item of list" :item="item"></slot>
</ul>
</div>`
})
//创建vue实例对象
var vm = new Vue({
el: '#root'
})
</script>
</body>