uniapp或小程序多级插槽slot会失效

项目场景:

uniapp 中使用 slot 插槽让用户自定义图标,插槽嵌套有三层(多层)会发现插槽失效的行为, 小程序端总是显示默认内容, H5端正常。

<slot name="customIcon">
	<img src="home.png" />  <!-- 默认内容 --->
</slot>

问题描述

举例什么是多级嵌套使用插槽?

例如:有一个Box组件,有两种Box类型:left 和 right,Box组件里面含有图标。多层级情况下,这时候Vue怎么去定义一个自定义图标的插槽 customIcon 呢?

<!-- Box.vue -->
<template>
	<div v-if="type == 'left'">
		<left-box>
			<template v-slot="customLeftIcon">
				<slot name="customIcon"></slot>
			</template>
		</left-box>
	</div>
	<div v-else-if="type == 'right'">...</div>
</template>
<!-- LeftBox.vue -->
<template>
	<div class="leftBox">
		<slot name="customLeftIcon">
			<img src="home.png" />
		</slot>
		<span>i am left box</span>
	</div>
</template>

使用这个Box组件并使用 customIcon 自定义图标用法如下:

<!-- 使用方法 -->
<template>
	<Box type="left">
		<img src="myHome.png" slot="customIcon" />
	</Box>
</template>

以上例子是H5环境的写法,如果没有自定义图标就会使用默认的图标,但是在微信小程序端,这个方式出来的效果就是无论有没有自定义图标都会使用默认的,这符合最终的效果。

坑1

小程序端,我尝试用这样的方法解决问题:手动判断用户有没有使用自定义插槽 $slots[‘customIcon’], 只有自定义了才会在子组件设置插槽。这里我不会再写使用方法,主要写实现:

<!-- Box.vue -->
<template>
	<div v-if="type == 'left'">
		<left-box>
			<template v-slot="customLeftIcon" v-if="$slots['customIcon']">
				<slot name="customIcon"></slot>
			</template>
		</left-box>
	</div>
	<div v-else-if="type == 'right'">...</div>
</template>

LeftBox.vue 与原来一致,最终效果不达标

坑2

搜了很多资料,说是 v-if 判断只能放置在里面,我把它改成这样:

<!-- Box.vue -->
<template>
	<div v-if="type == 'left'">
		<left-box>
			<template v-slot="customLeftIcon">
				<slot name="customIcon" v-if="$slots['customIcon']"></slot>
			</template>
		</left-box>
	</div>
	<div v-else-if="type == 'right'">...</div>
</template>

还是不行!


原因分析:

这个原因我不知道,也不想知道,更加不愿意知道,奇奇怪怪的问题,只能归结为小程序插槽的坑。

解决方案:

有效的解决办法:

父组件Box传一个 isCustomIcon 进去:

<!-- Box.vue -->
<template>
	<div v-if="type == 'left'">
		<left-box :isCustomIcon="!!$slots['customIcon']">
			<template v-slot="customLeftIcon">
				<slot name="customIcon"></slot>
			</template>
		</left-box>
	</div>
	<div v-else-if="type == 'right'">...</div>
</template>
<!-- LeftBox.vue -->
<template>
	<div class="leftBox">
		<!-- 父组件传来的 isCustomIcon -->
		<template v-if="isCustomIcon">
			<slot name="customLeftIcon" />
		</template>
		<img v-else src="home.png" />
		<span>i am left box</span>
	</div>
</template>

这样就没有问题了!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我可以回答该问题。以下是一个示例代码: ``` <template> <view class="container"> <view class="item"> <text>省份:</text> <picker-view :value="value1" @change="onChange1" class="picker" > <picker-view-column v-for="item in provinceList" :key="item">{{item}}</picker-view-column> </picker-view> </view> <view class="item"> <text>城市:</text> <picker-view :value="value2" @change="onChange2" class="picker" > <picker-view-column v-for="item in cityList" :key="item">{{item}}</picker-view-column> </picker-view> </view> <view class="item"> <text>区域:</text> <picker-view :value="value3" @change="onChange3" class="picker" > <picker-view-column v-for="item in areaList" :key="item">{{item}}</picker-view-column> </picker-view> </view> </view> </template> <script> export default { data() { return { provinceList: ['北京', '上海', '广东'], cityList: [], areaList: [], value1: 0, value2: 0, value3: 0 }; }, methods: { onChange1(e) { const index = e.detail.value; const province = this.provinceList[index]; this.cityList = this.getCityList(province); this.areaList = this.getAreaList(province, this.cityList[0]); this.value1 = index; this.value2 = 0; this.value3 = 0; }, onChange2(e) { const index = e.detail.value; const city = this.cityList[index]; this.areaList = this.getAreaList(this.provinceList[this.value1], city); this.value2 = index; this.value3 = 0; }, onChange3(e) { const index = e.detail.value; this.value3 = index; }, getCityList(province) { // 根据选中的省份返回城市列表 // 省份可以是一个字符串,也可以是一个数字索引 }, getAreaList(province, city) { // 根据选中的省份和城市返回区域列表 // 省份和城市都可以是字符串,也可以是数字索引 } } }; </script> ``` 该代码使用了三个 `picker-view` 组件,分别用于选择省份、城市和区域。每次选择省份,都重新计算城市和区域列表,然后将当前选中的值重置为 0。选择城市时重新计算区域列表,选中区域后,不再执行其他操作。 注意,该代码只是一个示例,具体的实现方式可能因为不同的需求而有所不同,请根据自己的需求进行调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值