插槽的作用:让组件内部的一些 结构 支持自定义。
例如:我们需要再页面中显示一个对话框,将其封装成一个组件。
当我们希望组件内容部分,不希望写死,就得用插槽来解决
插槽的分类:
基本使用
MyDialog组件
1.组件内需要定制的结构部分,使用<slot></slot>占位
<div class="dialog-content">
<!-- 1. 在需要定制的位置,使用slot占位 -->
<slot></slot>
</div>
App.vue组件
2.使用组件时,<MyDialog></MyDialog>标签内部,传入结构替换slot。
<div class="app">
<!-- 2. 在使用组件时,组件标签内填入内容 -->
<MyDialog>
<div>你确认要退出么</div>
</MyDialog>
<MyDialog>
<p>你确认要删除吗</p>
<p>你确认要删除吗</p>
<p>你确认要删除吗</p>
</MyDialog>
</div>
通过插槽完成了内容的定制,传什么显示什么,但是如果我们在组件使用的时候,不传,则是空白
那么能否给插槽设置 默认显示内容呢?
MyDialog组件
1.
<div class="dialog-content">
<!-- 往slot标签内部,编写内容(会被作为后备默认内容) -->
<slot>我是默认的插槽内容</slot>
</div>
App.vue组件
<div class="app">
//一个不传值,一个传值
<MyDialog></MyDialog>
<MyDialog>
我传递了内容哦!
</MyDialog>
</div>
说白了就是当不给组件传值的时候,就显示slot标签内部的内容。
当一个组件有多个结构,需要进行定制内容
此时的默认插槽是无法解决该问题
默认插槽:只能有一个定制位置
所以,得使用具名插槽来解决
MyDialog组件
1.
<div class="dialog-header">
<!-- 一但插槽起了名字,就是具名插槽,(只支持定向分发) -->
<slot name="head"></slot>
</div>
<!-- 内容 -->
<div class="dialog-content">
<slot name="content"></slot>
</div>
<!-- 底部 -->
<div class="dialog-footer">
<slot name="footer"></slot>
</div>
App.vue组件
2.切记用template包裹起来,根据插槽名分发内容
<MyDialog>
<!-- 需要通过template包裹,template配合 v-slot:名字 来分发对应标签 -->
<template v-slot:head>
<div>我是大标题</div>
</template>
<template v-slot:content>
<div>我是内容</div>
</template>
<!-- 简写#插槽名 -->
<template #footer>
<button>确认</button>
<button>取消</button>
</template>
</MyDialog>
作用于插槽:定义slot插槽的同时,是可以传值的。给 插槽 上可以 绑定数据,将来 使用组件时可以使用。
使用场景:封装表格组件
所有添加的属性,都会被收集到一个对象中
{ id: 3 , msg: '测试'}
在 template中,通过 #插槽名="obj"
接收,默认插槽名为: default → #default="obj"
这里使用一个简单的表格删除和查询来练习插槽
首先是我们呢的子组件代码
<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>
App.vue父组件代码
<template>
<div>
<MyTable :data="list">
<!-- 3. 通过template #插槽名="变量名" 接收 -->
<template #default = "obj">
<button @click="del(obj.row.id)">删除</button>
</template>
</MyTable>
<MyTable :data="list2">
<!-- 这里是一样的:需要使用template包裹 -->
<template #default="{row}">
<button @click="look(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 },
]
}
},
methods: {
del (id) {
// 删除功能:使用filter过滤
this.list = this.list.filter( item => item.id !== id)
},
look (row) {
alert(`姓名:${row.name}; 年纪:${row.age}`)
}
},
components: {
MyTable
}
}
</script>
这里主要讲解了插槽的语法和基本的使用。