z***@163.com
z***@163.com
  • 发布:2025-08-07 14:37
  • 更新:2025-08-07 16:11
  • 阅读:79

【报Bug】在组件的v-for里使用slot时多渲染了一个<slot></slot>导致微信开发工具报好多警告

分类:uni-app

产品分类: uniapp/小程序/微信

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: window 10

HBuilderX版本号: 4.75

第三方开发者工具版本号: 1.06.2504010 win32-x64

基础库版本号: 3.7.8

项目创建方式: CLI

CLI版本号: 3.0.0-alpha-4070620250731001

示例代码:
<swiper-item class="flexColumn fBlock" v-for="item,index in dataList" :key="item?.id||index">  
    <slot :item="item" :index="index"></slot>  
</swiper-item>

操作步骤:
<swiper-item class="flexColumn fBlock" v-for="item,index in dataList" :key="item?.id||index">  
    <slot :item="item" :index="index"></slot>  
</swiper-item>

预期结果:

只编译出一个slot

实际结果:

看版本对比,新版编译的时候特意加了默认插槽的判断,所以 编译出了两个slot,一个是具名插槽,一个是默认插槽,导致默认插槽在开发者工具里报了好多警告。

bug描述:

在v-for里写入默认插槽,看下面代码

<swiper-item class="flexColumn fBlock" v-for="item,index in dataList" :key="item?.id||index">  
    <slot :item="item" :index="index"></slot>  
</swiper-item>

编译出来的结果多了个<slot></slot>导致微信开发工具报了一堆警告([Component] More than one slot named "default" are found inside a single component instance (in component "components/bSwiper/bSwiper"). The first one was accepted.),编译结果看下面代码

<swiper-item wx:for="{{a}}" wx:for-item="item" wx:key="d" class="flexColumn fBlock data-v-4d28a2b6">  
      <slot name="{{item.a}}"></slot>  
      <slot></slot>  
  </swiper-item>>

看了下编译的文件codegen.js。新版多了对默认插槽的判断。代码如下

if (node.tagType === compiler_core_1.ElementTypes.SLOT) {  
                const isEmptyDefaultSlot = node.props.some((p) => (p.type === compiler_core_1.NodeTypes.ATTRIBUTE &&  
                    p.name === 'name' &&  
                    p.value?.content === uni_shared_1.SLOT_DEFAULT_NAME) ||  
                    (p.name === 'bind' &&  
                        p.slotName ===  
                            uni_shared_1.SLOT_DEFAULT_NAME)) && node.children.length === 0;  
                // 当存在 <slot name="default" :xxx="xxx"><slot> 时,在后面添加 <slot></slot>,使默认插槽生效  
                if (isEmptyDefaultSlot) {  
                    genSlot(node, context);  
                    return genSlot((0, shared_1.extend)({}, node, { props: [], children: [], loc: {} }), context);  
                }  
                return genSlot(node, context);  
            }

之前版本是没有isEmptyDefaultSlot 的判断的。多了这个判断后,虽然代码可以使用,但是报了好多警告。

2025-08-07 14:37 负责人:无 分享
已邀请:
DCloud_UNI_JBB

DCloud_UNI_JBB

你的完整的代码是怎么写的?

  • z***@163.com (作者)

    不是单独这一个组件这样的。其他所有组件都是这样的。

    2025-08-07 15:40

  • DCloud_UNI_JBB

    回复 z***@163.com: 发下可复现demo

    2025-08-07 15:43

z***@163.com

z***@163.com (作者)

<template>  
    <swiper class="bSwiper"  @change="change">  
        <swiper-item class="flexColumn fBlock" v-for="item,index in dataList" :key="item?.id||index">  
            <slot :item="item" :index="index"></slot>  
        </swiper-item>  
    </swiper>  
</template>  

<script setup lang="ts">  
  defineOptions({  
    name: "bSwiper",  
    options: {  
        virtualHost: true,  
        multipleSlots: true,  
    },  
  })  
    type DataItem = {  
        image_url : string;  
    [key:string]:any;  
    };  
    const props = defineProps({  
        dataList: {  
            type: Array as PropType<DataItem[]>,  
            default: () => []  
        },  
    })  
    const emits = defineEmits(["change"]);  
    //const current = ref<any>(0);  

    const change = (e : AnyObject) => {  
        emits("change", e.detail)  
    }  
</script>

类似这样的简单封装一个Swiper组件。编译出来的就是两个slot。就是for里面有默认插槽的情况下都会出现编译出两个slot的情况。编译结果就是下面这样,多了一个<slot></slot> ,代码虽然可以使用,不过开发工具报好多警告的:

<swiper-item wx:for="{{a}}" wx:for-item="item" wx:key="d" class="flexColumn fBlock data-v-4d28a2b6">    
      <slot name="{{item.a}}"></slot>    
      <slot></slot>    
  </swiper-item>>

我临时把编译文件改回以前的了。

if (isEmptyDefaultSlot) {    
                    return  genSlot(node, context);  //临时解决bug,提前return了,不会编译出两个slot。  
                    return genSlot((0, shared_1.extend)({}, node, { props: [], children: [], loc: {} }), context);    
                }  
  • DCloud_UNI_JBB

    你外面怎么使用这个组件?isEmptyDefaultSlot 是为了解决默认插槽的显示问题,我看看怎么优化下这里

    2025-08-07 16:06

z***@163.com

z***@163.com (作者)

类似这样:

<bSwiper :dataList="swiperBanner">  
                    <template v-slot="{item}">  
                        <view class="fBlock" @tap="goto(item.links)">  
                            <bImg noBgColor class="sImg iSwiper" :lazyLoad="false" :defaultType="999" :borderRadius="10" :src="item.litpic">  
                            </bImg>  
                        </view>  
                    </template>  
                </bSwiper>

要回复问题请先登录注册