Vue中的插槽 -----具名插槽、作用域插槽
定义:插槽就是在子组件中的提供给父组件使用的一个占位符,用<slot></slot>
表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的<slot></slot>
标签。
举例:主机上的usb插孔 就是子组件中使用的插槽<slot></slot>
,而u盘既是父组件
在这个usb插孔上需要填充的任何模板代码 (最直接的是u盘 [ 模板代码 ] 随时可以插入,但插槽的存在决定着填充的内容是否渲染)
使用插槽的原因:当我们在父组件中给子组件标签内定义内容时,该内容是不会被渲染的
1、默认插槽:
描述:默认插槽就是指没有名字的插槽,子组件未定义名字的插槽,父级将会把 未指定插槽的填充的内容填充到默认插槽中
<div id="app">
<child>插入的内容不会被渲染</child>
</div>
<script src="../vue.js"></script>
<script>
const Child = {
template: `
<div class="child">
子组件渲染的内容
</div>
`
}
Vue.component("child",Child)
var vm = new Vue({
el: '#app',
});
</script>
结果:(在父组件中添加的内容不显示,而是显示了子组件的内容,)
使用插槽:
<div id="app">
<!-- 使用插槽 -->
<!-- <child>插入的内容不会被渲染</child> -->
<p class="split_line"></p>
<!-- 使用插槽插入内容 -->
<child>这是使用插槽插入的内容</child>
</div>
<script src="../vue.js"></script>
<script>
const Child = {
template: `
<div class="child">
<h3>子组件渲染的内容</h3>
<slot></solt> <!-- 使用插槽 -->
</div>
`
}
Vue.component("child",Child)
var vm = new Vue({
el: '#app',
});
</script>
结果:
2、具名插槽
说明:具名插槽就是给插槽取个名字
。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中。
(写法一)示例代码:
<div id="app">
<child>
<!--向插槽名字before插入内容 -->
<p slot="before">在p元素之前</p>
<!--向插槽名字after插入内容 -->
<p slot="after">在p元素之前</p>
</child>
</div>
<script src="../vue.js"></script>
<script>
const Child = {
template: `
<div>
<slot name="before"></slot> <!--使用插槽并定义名字 -->
<h3>子组件渲染的内容</h3>
<slot name="after"></slot> <!--使用插槽并定义名字 -->
</div>
`
}
Vue.component("child",Child)
var vm = new Vue({
el: '#app',
});
</script>
(写法二)示例代码:
v-slot:插槽名
可以简写成#插槽名
- 注意:v-slot:插槽名仅仅适用于
1、<template>
2、组件 (对于一个单独的带 prop 的默认插槽)
<div id="app">
<child>
<!--
<template v-slot:before>
<p>在h3元素之前</p>
</template>
<template v-slot:after>
<p>在h3元素之后</p>
</template>
-->
<!-- 上面写法等同于 -->
<template #before>
<p>在h3元素之前</p>
</template>
<template #after>
<p>在h3元素之后</p>
</template>
</child>
<!-- -->
</div>
<script src="../vue.js"></script>
<script>
const Child = {
template: `
<div>
<slot name="before"></slot>
<h3>h3标签:子组件渲染的内容</h3>
<slot name="after"></slot>
</div>
`
}
Vue.component("child",Child)
var vm = new Vue({
el: '#app',
});
</script>
上述结果:
总结上述:
(1). 父级的填充内容如果指定到子组件的没有对应名字插槽,那么该内容是不会被填充到默认插槽中。
(2). 如果子组件没有默认插槽,而父级的填充内容指定到默认插槽中,那么该内容就“不会”填充到子组件的任何一个插槽中。
(3). 如果子组件有多个默认插槽,而父组件所有指定到默认插槽的填充内容,将“会” “全都”填充到子组件的每个默认插槽中。
3、作用域插槽
说明:作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。
常用场景:
- 如果子组件中的某一部分的数据,每个父组件都会有自己的一套对该数据的不同的呈现方式,这时就需要用到作用域插槽。
对比案例代码:
<div id="app">
<child :list="list"></child>
<child :list="list"></child>
</div>
<script src="../vue.js"></script>
<script>
const Child = {
template: `<div>
<ul>
<li v-for="(item,index) in list" :key="index">
元素:{{item}} ---- 下标:{{index}}
</li>
</ul>
</div>`,
props:{
list:Array
}
}
const vm = new Vue({
el: '#app',
// 注册组件
components: {
Child
},
data() {
return {
list: [1, 2, 3]
}
},
})
</script>
结果:
使用作用域插槽 案例代码:
<div id="app">
<!-- 作用域插槽 -->
<cmp-two :list="list">
<template v-slot="{item,index}">
<li>元素内容{{item}} - 下标{{index}}</li>
</template>
</cmp-two>
<cmp-two :list="list">
<template v-slot="{item,index}">
<li>下标{{index}} - 元素内容{{item}}</li>
</template>
</cmp-two>
</div>
<script src="../vue.js"></script>
<script>
const cmpTwo = {
template:
`<div>
<ul>
<slot v-for="(item,index) in list" :item="item" :index="index"></slot>
</ul>
</div>`,
props:{
list:Array
},
}
const vm = new Vue({
el: '#app',
// 注册组件
components: {
cmpTwo
},
data() {
return {
list: [1, 2, 3]
}
},
})
</script>
结果: