这是我参与8月更文挑战的第18天,活动详情查看:8月更文挑战
一、场景需求
<div id="app">
<child content="<p>你好</p>"></child>
</div>
Vue.component('child', {
props: ['content'],
template: `<div>
<h3>hello</h3>
{{content}}
</div>`
})
显然,上述效果不是我们想要的。那如何解决呢?vue官方为我们提供了<slot>
元素作为承载分发内容的出口。这样就可以实现父组件向子组件优雅地传递dom结构,子组件能够完美解析DOM。
二、slot详解
通俗易懂的讲,slot具有“占坑”的作用,在子组件占好了位置,那父组件使用该子组件标签时,新添加的DOM元素就会自动填到这个坑里面。如下:
<child>
<p>你好</p>
</child>
Vue.component('child', {
props: ['content'],
template: `<div>
<h3>hello</h3>
<slot><slot>
</div>`
})
渲染后的结果就是:
注意: 如果有多个DOM元素,会一起插入到这个标签内
三、具名插槽
假设我们需要将父组件添加的HTML标签放在子组件里的不同位置。需要怎么实现呢?上面已经说了,<slot>
具有占坑作用。那么当父组件的HTML标签放到子组件的不同位置时,可以给子组件占的每一个坑取名,将父组件添加的HTML元素添加到指定名字的坑,就实现了分发内容在不同位置显示。
实现方式:
-
先在子组件对应分发
<slot>
标签里,添加name='name名'
属性; -
然后父组件在要分发的标签里添加
slot='name名'
属性,然后就会将对应的标签放在对应的位置了。
<div id="app">
<child>
<div class="header" slot="header">头部</div>
<div class="footer" slot="footer">底部</div>
</child>
</div>
Vue.component('child', {
props: ['content'],
template: `<div>
<slot name='header'></slot>
<h3>hello</h3>
<slot name='footer'><slot>
</div>`
})
具名插槽在父组件没有定义
<slot>
时可以设置默认内容,<slot name='header'>默认内容</slot>
。
四、作用域插槽
作用域插槽其实就是带数据的特殊类型的插槽,用作一个 (能被传递数据的) 可重用模板,来代替已经渲染好的元素。当一个组件需要重复使用时可以用到;作用域插槽适合的场景是至少包含三级以上的组件层级,是一种优秀的组件化方案!
<div id="app">
<child>
<template slot-scope="childData">
<li>{{childData.item}}</li>
</template>
</child>
</div>
Vue.component('child', {
props: ['content'],
data: function() {
return {
list: ['A', 'B', 'C']
}
},
template: `<div>
<h3>hello</h3>
<ul>
// item为向上层传递的数据,单个slot在调用时转化为作用域内的多个标签
<slot v-for="item of list" :item="item"></slot>
</ul>
</div>`
})
详细解析:
-
slot-scope
相当于是一个对象,这个对象里面的数据就是子组件插槽绑定传上来的; -
<template>
方式是固定的模版,必写; -
子组件中的
item
为向上层传递的数据,单个slot在调用时转化为作用域内的多个标签。
~~别走,点个赞吧~~~~