vue -- 组件插槽 默认插槽 具名插槽 作用域插槽

组件插槽

插槽Slot
插槽的使用过程其实是抽取共性 预留不同
我们会将共同的元素 内容依然在组件内进行封装
同时会将不同的元素使用slot作为占位符 让外部决定到底显示什么样的元素

如何使用slot
Vue中将< slot >元素作为承载分发内容的出口
在封装组件中 使用特殊的元素 < slot >就可以为封装组件开启一个插槽
该插槽插入什么内容取决于父组件如何使用

默认插槽

如果没有插入对应的内容 我们需要显示一个默认的内容
我们可以插入普通的内容 html元素 组件都是可以的

下面展示了怎么设置插槽内容是一个按钮 超链接 图片 。。。
在 ShowMessage.vue中

<template>
	<div class="content">
		<slot>
			<p>我是默认内容</p>
		</slot>
	</div>
</template>

在app.vue中

<template>
	<div class="app">
		<!-- 内容是一个按钮button -->
		<show-message title="哈哈">
			<button>我是按钮元素</button>
		</show-message>

		<!-- 内容是一个超链接 -->
		<show-message>
			<a href="#">百度</a>
		</show-message>

		<!-- 内容是一张图片 -->
		<show-message>
			<img src="@/assets/logo.png" alt="">
		</show-message>

		<!-- 内容没有传递 -->
		<show-message></show-message>
	</div>
</template>

<script>
import ShowMessage from './ShowMessage.vue';
export default {
	components: {
		ShowMessage
	}
}
</script>

<style scoped>

</style>

具名插槽

当我们希望插槽对应的显示 这时候我们就可以使用具名插槽
具名插槽就是给插槽起一个名字 < slot >元素有一个特殊的attribute:name
一个不带name的slot 会带有隐含的名字default

在NavBar.vue中

	<div class="nav-bar">
		<div class="left">
			<slot name="left">left</slot>
		</div>
		<div class="center">
			<slot name="center">center</slot>
		</div>
		<div class="right">
			<slot name="default">right</slot>
		</div>
	</div>

在app.vue中

	<nav-bar>
		<template v-slot:left>
			<button>{{leftText}}</button>
		</template>
		<template v-slot:center>
			<span>内容</span>
		</template>
		<template v-slot:right>
			<a href="#">连接</a>
		</template>
	</nav-bar>

动态插槽名
1.目前我们使用的插槽名称都是固定的
2.比如 v-slot:left v-slot:center等
3.我们可以通过 v-slot:[name]方式动态绑定一个名称

<template>
	<nav-bar>
		<template v-slot:[position]>
		</template>
	</nav-bar>
</template>
<script>
import NavBar from './NavBar.vue'
export default{
	data(){
		return {
			position:'center'	
		}
	],
	components:{
		NavBar
	}
}
</script>

具名插槽使用的时候缩写
与v-on 于 v-bind一样 v-slot也有缩写
即把参数之前的所有内容(v-slot:)替换为#

	<nav-bar>
		<template #left>
			<button>{{leftText}}</button>
		</template>
		<template #center>
			<span>内容</span>
		</template>
		<template #right>
			<a href="#">连接</a>
		</template>
	</nav-bar>
渲染作用域

在vue中有渲染作用域的概念
父级模板里的所有内容都是在父级作用域中编译的
子模板里的所有内容都在子作用域中编译的

例如 对于自身data中的属性 是可以通过{{}}访问到 当时在插槽中是不能访问的

作用域插槽

但是有时候我们希望插槽可以访问到子组件中的内容
1.当一个组件被用来渲染一个数组元素时 我们使用插槽 并且希望插槽中没有显示每项内容
2.Vue给我们提供了作用域插槽
在这里插入图片描述如果我们的插槽是默认插槽default,那么在使用的时候 v-slot:default="slotProps"可以简写为v-slot=“slotProps”
在这里插入图片描述
并且如果我们的插槽只有默认插槽时,组件的标签可以被当做插槽的模板来使用,这样,我们就可以将 v-slot 直接用在组件上
在这里插入图片描述

作用域插槽的案例

<template>
	<div class="tab-control">
		<template v-for="(item,index) in titles" :key="item">
			<div class="tab-control-item" @click="itemClick(index)" :class="{active:index === currentIndex}">
				<slot :item2="item" abc="cba">
					<span>
						{{item}}
					</span>
				</slot>
			</div>
		</template>
	</div>
</template>

<script>
export default {
	emits: ["tabItemClick"],
	props: {
		titles: {
			type: Array,
			default: () => []
		}
	},
	data() {
		return {
			currentIndex: 0
		}
	},
	methods: {
		itemClick(index) {
			this.currentIndex = index
			this.$emit('tabItemClick', index)
		}
	}
}
</script>

<style scoped>
.tab-control {
	display: flex;
	height: 44px;
	line-height: 44px;
	text-align: center;
}

.tab-control-item {
	flex: 1
}

.tab-control-item.active {
	color: red;
	font-weight: 700;
}

.tab-control-item.active span {
	border-bottom: 3px solid red;
	padding: 8px;
}
</style>
<template>
	<div class="app">
		<!-- 1 tab-control -->
		<tab-control :titles="['衣服','鞋子','裤子']" @tab-item-click="tabItemClick"></tab-control>

		<h1>{{pageContents[currentIndex]}}</h1>

		<tab-control :titles="['衣服','鞋子','裤子']" @tab-item-click="tabItemClick">
			<!-- 独占默认插槽的简写 -->
			<template v-slot="props">
				<button>{{props.item2}}</button>
			</template>
		</tab-control>

		<tab-control :titles="['衣服','鞋子','裤子']" @tab-item-click="tabItemClick">
			<template #default="props">
				<a href="#">{{props.item2}}</a>
			</template>
		</tab-control>
		<tab-control v-slot="props" :titles="['衣服','鞋子','裤子']" @tab-item-click="tabItemClick">
			<a href="#">{{props.item2}}</a>
		</tab-control>

	</div>
</template>

<script>
import TabControl from './TabControl.vue';
export default {
	components: {
		TabControl
	},
	data() {
		return {
			pageContents: ["衣服列表", "鞋子列表", "裤子列表"],
			currentIndex: 0
		}
	},
	methods: {
		tabItemClick(index) {
			console.log(index);
			this.currentIndex = index
		}
	}
}
</script>

<style lang="scss" scoped>

</style>
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_聪明勇敢有力气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值