1.插槽的基本认识:
作用:让组件内部的一些结构支持自定义
插槽的分类:
1.默认插槽(组件内只能定制一处结构)
2.具名插槽(组件内可以定制多次结构)
简单而言:就是你希望封装一个组件,这个组件会在多个地方使用,但是每个使用的地方其中的内容部分又是不同的,这个时候你希望自定义,就会运用到插槽。
2.默认插槽的基础语法:
1.组件内需要定制的部分用<slot></slot>占位
2.使用组件时,<组件名></组件名>在标签内容传入替换slot的内容
下面进行代码演示:
使用slot标签占位
完成的效果图:
此时我们又会面临一个问题,如果我不给自定义内容,就不会有任何内容,这样一片空白实在是不好看。那我们如何加默认值(设置默认内容)
3.插槽的后备内容:
1.语法:在<slot>标签内,放置内容,作为默认显示内容。
作用:1.组件标签使用时没有传入内容,会slot会显示后备内容。
2.组件标签使用时有传入内容,则slot会被整体替换掉。
下面进行代码演示:
效果图:
4.插槽—具名插槽(具有名字的插槽)
上面已经讲解了默认插槽,但是它有一个明显的缺点就是只能定制一个地方。而下面所说的具名插槽就可以很好的解决这个问题。
作用:一个组件内有多处结构,需要外部传入标签,进行定制。
1.具名插槽语法:
1.多个slot使用name属性区分名字
2.template配合v-slot:名字来分发对应的标签。
3.为了方便官方(v-slot:插槽名可以简写成#插槽名)
下面进行代码演示:
效果图:
使用#插槽名演示
5.作用域插槽(是插槽的一个传参语法):
作用域插槽:定义slot插槽的同时,可以传值的,给插槽上可以绑定数据,将来使用组件时可以使用。
使用场景:
1.父传子需要渲染内容时
2.比如我们常使用的删除、编辑等功能都需要当前项的id值,但是id属于组件内部的数据通过作用域插槽传值绑定,进而使用。
作用域插槽的基本使用步骤:
1.给slot标签,已添加属性的方式传值
2.所有添加的属性,都会被收集到一个对象中去。
3.在template中,通过“#插槽名字=“obj””接收(这里的obj可以自定义,就是个对象名而已),默认插槽名为default
下面进行代码演示:
组件:MyTable.vue代码:
<template>
<table class="my-table">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年纪</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in data" :key="item.id">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>
<!-- 1.给slot标签已添加属性的方式传值 -->
<slot :row="item" msg="测试文本"></slot>
<!-- 2.会将所用的属性添加到一个对象中去 -->
</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
props: {
data: Array,
},
}
</script>
<style scoped>
.my-table {
width: 450px;
text-align: center;
border: 1px solid #ccc;
font-size: 24px;
margin: 30px auto;
}
.my-table thead {
background-color: #1f74ff;
color: #fff;
}
.my-table thead th {
font-weight: normal;
}
.my-table thead tr {
line-height: 40px;
}
.my-table th,
.my-table td {
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
}
.my-table td:last-child {
border-right: none;
}
.my-table tr:last-child td {
border-bottom: none;
}
.my-table button {
width: 65px;
height: 35px;
font-size: 18px;
border: 1px solid #ccc;
outline: none;
border-radius: 3px;
cursor: pointer;
background-color: #ffffff;
margin-left: 5px;
}
</style>
下面是App.vue代码:
<template>
<div>
<!-- :data="list"相当于父传子 -->
<MyTable :data="list">
<!-- 注意要用<template></template>包裹 -->
<!-- 由于我们使用的是默认插槽,所以用default -->
<!-- 3.通过template #插槽名="变量名" 接收 -->
<template #default="obj">
<button @click="del(obj.row.id)">删除</button>
</template>
</MyTable>
<MyTable :data="list2">
<template #default="{row}">
<!-- 这个对象也支持结构 -->
<button @click="show(row)">查看</button>
</template>
</MyTable>
</div>
</template>
<script>
import MyTable from './components/MyTable.vue'
export default {
data () {
return {
list: [
{ id: 1, name: '张小花', age: 18 },
{ id: 2, name: '孙大明', age: 19 },
{ id: 3, name: '刘德忠', age: 17 },
],
list2: [
{ id: 1, name: '赵小云', age: 18 },
{ id: 2, name: '刘蓓蓓', age: 19 },
{ id: 3, name: '姜肖泰', age: 17 },
]
}
},
components: {
MyTable
},
methods:{
del(id){
this.list=this.list.filter(item=>item.id!==id)
},
show(row){
console.log(row)
}
}
}
</script>
效果图: