插槽概述
Vue
中提供了一种语法:插槽slot
,可以在一个网页视图中预留数据位置
Vue
中针对视图中占用位置和数据传递方式的不同,区分为:
- 匿名插槽
- 具名插槽
- 作用域插槽
匿名插槽
匿名插槽主要用来封装通用视图,如果视图中只有一个位置的数据不一致 ,就可以通过 <slot></slot>
预留一个插槽位置,父组件在使用子组件时就可以给插槽位置添加自定义数据
子组件
<template>
<div class="box-list">
<h2>自定义标题 - 展示列表数据</h2>
<!-- 不一致的数据展示部分,预留插槽:让父组件使用子组件传递视图数据 -
->
<!-- slot标签没有name属性,所以称为 匿名插槽-->
<slot> 默认的视图数据(父组件如果没有传递视图数据就展示默认视图)
</slot>
</div>
</template>
父组件
<template>
<div id="app">
<h2>入口模块</h2>
<h4>1、匿名插槽的使用</h4>
<!-- 开始标签和结束标签中没有传递视图数据-->
<SlotComp01></SlotComp01>
<hr>
<SlotComp01>
<!-- 开始标签和结束标签中,添加内容:默认占用插槽的位置-->
<ul>
<li>不信谣、不传谣,半夜偷偷焊铁条</li>
<li>抗疫~ 静默不能代替管控</li>
</ul>
</SlotComp01>
<hr>
</div>
</template>
<script>
// 导入
import SlotComp01 from "./pages/SlotComp01"
export default {
components: {
// 注册
SlotComp01
}
}
</script>
具名插槽
封装的子组件中,视图结构一致,但是多个位置的数据可能不一致,需要在子组件中预留多个可以插入数据的位置,就需要用到具名插槽(命名插槽)
子组件
<tempate>
<div class="box-msg">
<!-- name="title"的具名插槽位置-->
<h2> <slot name="title">默认标题位置</slot></h2>
<!-- 匿名插槽位置-->
<p> <slot> 默认内容位置</slot> </p>
<div>
<!-- name="footer"的具名插槽位置-->
<slot name="footer"> 默认注意事项位置 </slot>
</div>
</div>
</tempate>
父组件
<template>
<div id="app">
<h4>2、具名插槽的使用</h4>
<div class="content">
<!-- 直接使用,不注入内容 -->
<SlotComp02></SlotComp02>
<!-- 给指定名称的插槽,添加内容 -->
<SlotComp02>
<!-- 给name="title"的插槽添加数据 -->
<template slot="title">
自定义标题
</template>
<!-- 给匿名插槽添加数据 -->
<span>自定义内容
</span>
<!-- 给name="footer"的插槽添加数据-->
<template slot="footer">
<span>自定义页脚</span>
</template>
</SlotComp02>
<!-- 给指定名称的插槽,添加内容 -->
<SlotComp02>
<!-- 给name="title"位置添加标题 : 简化语法-->
<template #title>
具名插槽简化
</template>
<!-- 给匿名插槽添加数据 -->
<p>给name="title"位置添加标题简化语法:#title</p>
<!-- 给name="footer"添加数据-->
<template #footer>
页脚内容
</template>
</SlotComp02>
</div>
</div>
</template>
<script>
import SlotComp02 from "./pages/SlotComp02"
export default {
components: {
SlotComp02
}
}
</script>
作用域插槽
父组件传递给子组件进行数据管理,匿名插槽/具名插槽都是数据的展示/查询,如果在子组件中需要修改数据时,如果将要改动的数据传递给父组
件,让父组件完成数据的改动,就需要使用到插槽。
子组件
<template>
<div class="box-table">
<table>
<tr>
<th>序号</th>
<th>名称</th>
<th>操作</th>
</tr>
<tr v-for="goods in goodsList" :key="goods.id">
<td>{{goods.id}}</td>
<td>{{goods.name}}</td>
<td>
<!-- 预留插槽:操作数据的方式可能不一致-->
<!-- 给插槽添加自定义属性,将数据通过属性传递给父组件 {row:
商品对象}-->
<slot :row="goods"></slot>
</td>
</tr>
</table>
</div>
</template>
<script>
export default {
// 声明自定义属性接收父组件数据
props: ['goodsList']
}
</script>
父组件
<template>
<div id="app">
<h3>展示商品数据</h3>
<SlotComp03 :goods-list="goodsList">
<!-- 通过v-slot指令接收插槽传递的属性数据 props: {row:商品对
象}-->
<template v-slot="props">
<button @click="check(props)">查看数据</button>
</template>
</SlotComp03>
<SlotComp03 :goods-list="goodsList">
<!-- 通过v-slot指令接收插槽传递的属性数据 props: {row:商品对
象}-->
<template v-slot="props">
<button @click="edit(props)">编辑</button>
<button @click="del(props)">删除</button>
</template>
</SlotComp03>
</div>
</template>
<script>
import SlotComp03 from "./pages/SlotComp03"
export default {
components: {
SlotComp03
},
data() {
return {
goodsList: [ // 商品数据
{id: 2, name: "华为"},
{id: 1, name: "小米"}
]
}
},
methods: {
check(props){
console.log("查看商品对象:", props.row)
},
edit(props){
console.log("编辑的商品:", props.row)
},
del(props){
console.log("准备删除:", props.row)
}
}
}
</script>