目录
作用:让组件内部的一些结构,支持自定义的,支持复用,假如我点击一个添加按钮弹出一个框进行询问是否选择添加,我删除一条数据想要弹窗给用户询问是否删除。这两条弹窗结构都是一样的,可以封装成插槽进行复用。
需求:要在页面中显示一个对话窗,封装成一个组件
问题:组件的内容不希望是固定的,弹窗中的内容希望支持自定义,如何实现?
插槽基本语法:
1:在组件中需要定制的结构部分,使用<slot></slot>占位
2:使用组件时,传入定制的结构替换slot
代码示例:
在父组件中使用两次子组件实现两个子组件展示的内容不同
<template>
<div>
<!-- 4: 测试默认插槽-->
<MyDialog>
爱吃豆的土豆
</MyDialog>
<MyDialog>
你确定要删除嘛
</MyDialog>
</div>
</template>
<script>
import testMyTag from '@/views/商品案例/MyTag.vue'
import testMyTable from '@/views/商品案例/MyTable.vue'
import houbeiMyDialog from '@/views/后备插槽/MyDialog.vue'
import MyDialog from '@/views/默认插槽/MyDialog.vue'
import MyTable from '@/views/作用域插槽/MyTable.vue'
import testMyDialog from '@/views/具名插槽/MyDialog.vue'
import testnexttick from '@/views/TestnextTick.vue'
import BaseFrom from '@/views/BaseFrom.vue'
import BaseChart from '@/views/BaseChart.vue'
import AAA from '@/views/Left.vue'
import BBB from '@/views/Right.vue'
import CCC from '@/views/aa.vue'
export default {
components:{
AAA,BBB,CCC,BaseChart,BaseFrom,testnexttick,testMyDialog,MyTable,MyDialog,houbeiMyDialog,testMyTag,testMyTable
},
data(){
return{
}
},
methods: {
}
</script>
<style lang="less" scoped>
.footer_wrap a.router-link-exact-active{
background-color: #007acc;
}
</style>
子组件代码示例:
<template>
<div class="dialog">
<div class="dialog-header">
<h3>友情提示</h3>
<span class="close">??</span>
</div>
<div class="dialog-content">
<!-- 1. 在需要定制的位置,使用slot占位 -->
<slot></slot>
</div>
<div class="dialog-footer">
<button>取消</button>
<button>确认</button>
</div>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
<style scoped>
* {
margin: 0;
padding: 0;
}
.dialog {
width: 470px;
height: 230px;
padding: 0 25px;
background-color: #ffffff;
margin: 40px auto;
border-radius: 5px;
}
.dialog-header {
height: 70px;
line-height: 70px;
font-size: 20px;
border-bottom: 1px solid #ccc;
position: relative;
}
.dialog-header .close {
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
}
.dialog-content {
height: 80px;
font-size: 18px;
padding: 15px 0;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dialog-footer button {
width: 65px;
height: 35px;
background-color: #ffffff;
border: 1px solid #e1e3e9;
cursor: pointer;
outline: none;
margin-left: 10px;
border-radius: 3px;
}
.dialog-footer button:last-child {
background-color: #007acc;
color: #fff;
}
</style>
效果:这样父组件中使用的两次相同子组件,内容可以做到不同
如果不在父组件中传值,可在子组件占位的<slot>默认值</slot>中填写默认值,当父组件中使用这个子组件进行传值的时候父组件传的值会覆盖默认值
?
需求:一个组件内有多处结构,需要外部传入标签,进行定制
默认插槽:一个的定制位置
就是说子组件有多个位置需要父组件传值进行定制。可以用具名插槽进行定制
代码示例:
父组件
<template>
<div>
<!-- 2: 测试具名插槽-->
<testMyDialog>
<template v-slot:head>
<div>
想她吗?
</div>
</template>
<template v-slot:middle>
<div>
旧人不如新年!
</div>
</template>
<template #bottom>
<button>确认</button>
<button>取消</button>
</template>
</testMyDialog>
</div>
</template>
<script>
import testMyTag from '@/views/商品案例/MyTag.vue'
import testMyTable from '@/views/商品案例/MyTable.vue'
import houbeiMyDialog from '@/views/后备插槽/MyDialog.vue'
import MyDialog from '@/views/默认插槽/MyDialog.vue'
import MyTable from '@/views/作用域插槽/MyTable.vue'
import testMyDialog from '@/views/具名插槽/MyDialog.vue'
import testnexttick from '@/views/TestnextTick.vue'
import BaseFrom from '@/views/BaseFrom.vue'
import BaseChart from '@/views/BaseChart.vue'
import AAA from '@/views/Left.vue'
import BBB from '@/views/Right.vue'
import CCC from '@/views/aa.vue'
export default {
components:{
AAA,BBB,CCC,BaseChart,BaseFrom,testnexttick,testMyDialog,MyTable,MyDialog,houbeiMyDialog,testMyTag,testMyTable
},
data(){
return{
}
},
methods: {
}
</script>
<style lang="less" scoped>
</style>
?子组件:
<template>
<div class="dialog">
<div class="dialog-header">
<slot name="head"></slot>
</div>
<div class="dialog-content">
<!-- 1. 在需要定制的位置,使用slot占位 -->
<slot name="middle"></slot>
</div>
<div class="dialog-footer">
<slot name="bottom"></slot>
</div>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
<style scoped>
* {
margin: 0;
padding: 0;
}
.dialog {
width: 470px;
height: 230px;
padding: 0 25px;
background-color: #ffffff;
margin: 40px auto;
border-radius: 5px;
}
.dialog-header {
height: 70px;
line-height: 70px;
font-size: 20px;
border-bottom: 1px solid #ccc;
position: relative;
}
.dialog-header .close {
position: absolute;
right: 0px;
top: 0px;
cursor: pointer;
}
.dialog-content {
height: 80px;
font-size: 18px;
padding: 15px 0;
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.dialog-footer button {
width: 65px;
height: 35px;
background-color: #ffffff;
border: 1px solid #e1e3e9;
cursor: pointer;
outline: none;
margin-left: 10px;
border-radius: 3px;
}
.dialog-footer button:last-child {
background-color: #007acc;
color: #fff;
}
</style>
效果:?
?
代码实现:
父组件:
<template>
<div>
<!-- 3: 测试作用域插槽 -->
<MyTable :data="list">
<!-- 3. 通过template #插槽名="变量名" 接收 -->
<template #default="obj">
<button @click="del(obj.row.id)">
删除
</button>
</template>
</MyTable>
<MyTable :data="list2">
<!-- 3. 通过template #插槽名="变量名" 接收 -->
<template #default="{ row }">
<button @click="show(row)">查看</button>
</template>
</MyTable>
</div>
</template>
<script>
import testMyTag from '@/views/商品案例/MyTag.vue'
import testMyTable from '@/views/商品案例/MyTable.vue'
import houbeiMyDialog from '@/views/后备插槽/MyDialog.vue'
import MyDialog from '@/views/默认插槽/MyDialog.vue'
import MyTable from '@/views/作用域插槽/MyTable.vue'
import testMyDialog from '@/views/具名插槽/MyDialog.vue'
import testnexttick from '@/views/TestnextTick.vue'
import BaseFrom from '@/views/BaseFrom.vue'
import BaseChart from '@/views/BaseChart.vue'
import AAA from '@/views/Left.vue'
import BBB from '@/views/Right.vue'
import CCC from '@/views/aa.vue'
export default {
components:{
AAA,BBB,CCC,BaseChart,BaseFrom,testnexttick,testMyDialog,MyTable,MyDialog,houbeiMyDialog,testMyTag,testMyTable
},
data(){
return{
// countvalue:0,
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 },
]
}
},
methods: {
}
</script>
<style lang="less" scoped>
.footer_wrap a.router-link-exact-active{
background-color: #007acc;
}
body {
margin: 0px;
}
.footer_wrap {
position: relative;
left: 0;
top: 0;
display: flex;
width: 100%;
text-align: center;
background-color: #333;
color: #ccc;
}
.footer_wrap a {
flex: 1;
text-decoration: none;
padding: 20px 0;
line-height: 20px;
background-color: #333;
color: #ccc;
border: 1px solid black;
}
.footer_wrap a:hover {
background-color: #555;
}
</style>
子组件:
<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. 将所有的属性,添加到一个对象中 -->
<!--
{
row: { id: 2, name: '孙大明', age: 19 },
msg: '测试文本'
}
-->
</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>