Gongjinwei
Gongjinwei
  • 发布:2025-11-27 14:38
  • 更新:2025-11-27 14:38
  • 阅读:17

【报Bug】UNIAPPXIOS UTS标准组件 在改组件快速切换v-if时 native-view @init 只要使用 e.detail.element 就会闪退崩溃

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Mac

PC开发环境操作系统版本号: 14.7.8 (23H730)

HBuilderX类型: 正式

HBuilderX版本号: 4.86

手机系统: Android

手机系统版本号: iOS 15

手机厂商: 苹果

手机机型: iphone x

页面类型: nvue

vue版本: vue3

打包方式: 云端

项目创建方式: HBuilderX

操作步骤:
<template>  
    <view class="xb-image-x" :class="new Map<string, boolean>([['unScaleToFill',mode !== 'scaleToFill']])">  
        <image class="xb-image-x-image" :src="src" :mode="mode" :lazy-load="lazyLoad" :fade-show="fadeShow" :webp="webp"  
            :show-menu-by-longpress="showMenuByLongpress" :draggable="draggable" @error="onError" @load="onLoad" v-if="src">  
        </image>  
        <!-- <text style="color: #fff; position: absolute; left: 0; top: 0; z-index: 99999; font-size: 40rpx;">{{status}}</text> -->  
        <template v-if="showLoading">  
            <view class="loading" v-if="status === 'loading'">  
                <image class="loading-image" src="/uni_modules/xb-image-x/static/xbImageXplaceholder.png" mode="aspectFill">  
                </image>  
                <view class="animation">  
                    <view style="width: 100px; height: 50px; margin: 0 auto;">  
                        <xb-n-lottie :json="lottieLoadingJson"></xb-n-lottie>  
                    </view>  
                </view>  
            </view>  
        </template>  
    </view>  
</template>  
<script setup>  
    import lottieLoadingJson from '@/static/lottie/Loading.json'  

    const emit = defineEmits(['error', 'load'])  

    const props = defineProps({  
        bindclass: {  
            type: String,  
            default: '',  
        },  
        src: {  
            type: String,  
            default: '',  
        },  
        mode: {  
            type: String,  
            default: 'scaleToFill',  
        },  
        lazyLoad: {  
            type: Boolean,  
            default: false,  
        },  
        fadeShow: {  
            type: Boolean,  
            default: false,  
        },  
        webp: {  
            type: Boolean,  
            default: true,  
        },  
        showMenuByLongpress: {  
            type: Boolean,  
            default: false,  
        },  
        draggable: {  
            type: Boolean,  
            default: false,  
        },  
        showLoading: {  
            type: Boolean,  
            default: true,  
        },  
    })  

    const status = ref('loading')  

    // 加载失败  
    const onError = (event: UniImageErrorEvent) => {  
        status.value = 'error'  
        emit('error', event)  
    }  

    // 加载成功  
    const onLoad = (event: UniImageLoadEvent) => {  
        status.value = 'success'  
        emit('load', event)  
    }  

    onMounted(() => {  
        removeHidden.value = true;  
    })  
</script>

xb-n-lottie.uvue

<template>  
    <!-- <view class="native-view-box"> -->  
    <native-view class="native-view" @init="onviewinit"></native-view>  
    <!-- </view> -->  
</template>  
<script setup lang="uts">  
    // #ifdef APP-IOS  
    import { NativeView } from "@/uni_modules/xb-lottie";  
    // #endif  
    let nativeView : NativeView | null = null  

    //声明属性  
    const props = defineProps<{  
        json : UTSJSONObject  
    }>()  

    //声明事件  
    const emit = defineEmits<{  
        (e : "init", event : UniNativeViewInitEvent) : void  
    }>()  

    //native-view初始化时触发此方法  
    function onviewinit(e : UniNativeViewInitEvent) {  
        console.log(e.detail.element)  
    }  

    defineExpose({  
    })  

    function onUnmounted() {  
        nativeView?.destroy()  
    }  

    onBeforeUnmount(() => {  
        onUnmounted()  
    })  
</script>

预期结果:

不出现闪退

实际结果:

闪退

bug描述:

<template>  
    <view class="xb-image-x" :class="new Map<string, boolean>([['unScaleToFill',mode !== 'scaleToFill']])">  
        <image class="xb-image-x-image" :src="src" :mode="mode" :lazy-load="lazyLoad" :fade-show="fadeShow" :webp="webp"  
            :show-menu-by-longpress="showMenuByLongpress" :draggable="draggable" @error="onError" @load="onLoad" v-if="src">  
        </image>  
        <!-- <text style="color: #fff; position: absolute; left: 0; top: 0; z-index: 99999; font-size: 40rpx;">{{status}}</text> -->  
        <template v-if="showLoading">  
            <view class="loading" v-if="status === 'loading'">  
                <image class="loading-image" src="/uni_modules/xb-image-x/static/xbImageXplaceholder.png" mode="aspectFill">  
                </image>  
                <view class="animation">  
                    <view style="width: 100px; height: 50px; margin: 0 auto;">  
                        <xb-n-lottie :json="lottieLoadingJson"></xb-n-lottie>  
                    </view>  
                </view>  
            </view>  
        </template>  
    </view>  
</template>  
<script setup>  
    import lottieLoadingJson from '@/static/lottie/Loading.json'  

    const emit = defineEmits(['error', 'load'])  

    const props = defineProps({  
        bindclass: {  
            type: String,  
            default: '',  
        },  
        src: {  
            type: String,  
            default: '',  
        },  
        mode: {  
            type: String,  
            default: 'scaleToFill',  
        },  
        lazyLoad: {  
            type: Boolean,  
            default: false,  
        },  
        fadeShow: {  
            type: Boolean,  
            default: false,  
        },  
        webp: {  
            type: Boolean,  
            default: true,  
        },  
        showMenuByLongpress: {  
            type: Boolean,  
            default: false,  
        },  
        draggable: {  
            type: Boolean,  
            default: false,  
        },  
        showLoading: {  
            type: Boolean,  
            default: true,  
        },  
    })  

    const status = ref('loading')  

    // 加载失败  
    const onError = (event: UniImageErrorEvent) => {  
        status.value = 'error'  
        emit('error', event)  
    }  

    // 加载成功  
    const onLoad = (event: UniImageLoadEvent) => {  
        status.value = 'success'  
        emit('load', event)  
    }  

    onMounted(() => {  
        removeHidden.value = true;  
    })  
</script>

xb-n-lottie.uvue

<template>  
    <!-- <view class="native-view-box"> -->  
    <native-view class="native-view" @init="onviewinit"></native-view>  
    <!-- </view> -->  
</template>  
<script setup lang="uts">  
    // #ifdef APP-IOS  
    import { NativeView } from "@/uni_modules/xb-lottie";  
    // #endif  
    let nativeView : NativeView | null = null  

    //声明属性  
    const props = defineProps<{  
        json : UTSJSONObject  
    }>()  

    //声明事件  
    const emit = defineEmits<{  
        (e : "init", event : UniNativeViewInitEvent) : void  
    }>()  

    //native-view初始化时触发此方法  
    function onviewinit(e : UniNativeViewInitEvent) {  
        console.log(e.detail.element)  
    }  

    defineExpose({  
    })  

    function onUnmounted() {  
        nativeView?.destroy()  
    }  

    onBeforeUnmount(() => {  
        onUnmounted()  
    })  
</script>

比如在以上代码逻辑中,某些图片已经加载过一次有缓存了,会快速触发status.value = 'success'导致<xb-n-lottie />组件消失 onviewinit 触发之后 哪怕是console.log(e.detail.element) 也会引起崩溃闪退,查看堆站日志发现
Thread 0 Crashed:
UniNativeViewComponent.sendInitEvent() + 636
→ layoutDidFinish()
→ _layoutDidFinish
→ UniJsBridge.registerPageFunction()
→ handleDisplayLink()

2025-11-27 14:38 负责人:无 分享
已邀请:

要回复问题请先登录注册