- 匿名插槽
- 具名插槽
- 作用域插槽
Question:
1.具名插槽与匿名插槽的区别?
同一个组件,不同的用户调用时渲染的内容不一样,在调用组件时通过slot的name来区分插槽,这个就是具名插槽的作用,而不传值不去指明slot的name值时,这个会调用组件的匿名插槽来渲染组件,可以理解为使用默认值来渲染。
2.作用域插槽是什么意思?
作用域插槽---乍听起来,是一个很抽象的概念。看了几遍官方文档,有了一些粗浅的认识,觉得这个名字取得还挺恰当的,因为它在一定范围内,延伸了子组件的作用域。
组件有编译作用域---父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子作用域中编译的。
看看官方的例子---
定义一个子组件,有个具名插槽son,并且通过属性绑定子组件的数据user。
const sonCom = {
template: `
<div>
<slot name="son" :user="user">子组件数据:{{user.firstName}}</slot>
</div>
`,
data() {
return {
user: {
firstName: '三',
lastName: '张'
}
}
}
}
父组件调用子组件时,假设不想展示firstName了,想展示lastName,按照下面这样写是不行的。
<div id="app">
<son-com>{{user.lastName}}</son-com>
</div>
因为user是在子组件的作用域中,父组件无法访问。
此时通过作用域插槽,可以做到。如下代码,通过v-slot指定绑定具名插槽son,通过自定义的scope接收子组件的user数据。
(注:v-slot指令是Vue2.6之后,作用域插槽的新语法,旧语法现在还保留,但3.0之后会移除。推荐新语法,简便写法是#son=“{user}”)
<div id="app">
<son-com v-slot:son="scope">{{scope.user.lastName}}</son-com>
</div>
从结果来看,可以认为作用域插槽延伸了子组件数据的作用范围,这样想,作用域插槽这个名字就不那么抽象了,而且顾名思义。
使用场景
例如,在使用elementUI组件库的表格组件时,表格的编辑和删除操作要用到作用域插槽。因为一个表格组件,就是当前组件的子组件。
此时我们通过作用域插槽很容易拿到当前表格行的索引和内容,这样就可以很方便地进行编辑展示、删除的操作。
并且,我们知道Vue是单向数据流。传递给子组件的数据,若要修改,应在父组件中处理。而我们通过作用域插槽,正好可以在父组件中修改数据,方便安全。
摘抄链接如下:简单理解Vue中的作用域插槽 - 思来享趣的文章 - 知乎 https://zhuanlan.zhihu.com/p/255241094
子组件:
<template>
<div :class="['my-btn',btnStyle]">
{{btnText}}
<div>
<!--匿名slot -->
<slot></slot>
<!-- 具名slot -->
<slot name="slot1"></slot>
<slot name="slot2" ></slot>
<slot name="childSlot" :data="data">
</slot>
</div>
</div>
</template>
<script>
export default {
props:{
btnStyle:String,
btnText:String
},
data () {
return {
data:['1','2','3'],
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<style>
.my-btn{
height:34px;
padding:0 15px;
border-radius: 5px;
border:none;
outline: none;
background-color: aliceblue;
}
.btn-warning{
background: red;
}
</style>
父组件:
<template>
<div id="app">
<h1>vue中插槽的实际应用</h1>
<my-button btnStyle='btn-warning' btnText='这是btnText'>
</my-button >
<!-- 匿名插槽 -->
<div :style="{background:'gray','margin-top':'50px'}">
<my-button>
<div>我是匿名slot</div>
</my-button>
</div>
<!-- 具名插槽 -->
<div :style="{background:'gray','margin-top':'50px'}">
<my-button>
<template v-slot:slot2>
<div style="background-color:gray">这是具名slot-2</div>
</template>
<template v-slot:slot1>
<div style="background-color:pink">这是具名slot-1</div>
</template>
</my-button>
</div>
<!-- 作用域插槽-用列表展示出来 -->
<div :style="{background:'gray','margin-top':'50px'}">
<my-button>
<template slot="childSlot" slot-scope="slotValue">
<ul>
<li v-for="(item,index) in slotValue.data" :key="index">{{item}}</li>
</ul>
</template>
</my-button>
</div>
</div>
</template>
<script>
import Button from '@/components/Button';
export default {
components:{
MyButton:Button,
}
}
</script>
<style>
</style>
效果图如下: