l***@gmail.com
l***@gmail.com
  • 发布:2024-07-18 15:23
  • 更新:2024-08-08 20:47
  • 阅读:279

【报Bug】uniapp-微信小程序调用 createIntersectionObserver 创建 observer 以后 disconnect 依然会引起内存泄漏

分类:uni-app

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

PC开发环境操作系统: Mac

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

第三方开发者工具版本号: 微信开发者工具 Stable 1.06.2405020

基础库版本号: 3.5.0

项目创建方式: CLI

CLI版本号: @vue/cli 5.0.8

示例代码:

模板项目 index.vue 改动

<template>  
    <view class="content">  
        <image class="logo" src="../../static/logo.png" @click="onClick"></image>  
        <view>  
            <text class="title">{{title}}</text>  
            <test v-if="showTest" />  
        </view>  
    </view>  
</template>  

<script lang="ts">  
  import Vue from 'vue';  
    import Test from './test.vue';  

    export default Vue.extend({  
        data() {  
            return {  
                title: 'Hello',  
                showTest: true,  
            }  
        },  
        components: {  
            Test,  
        },  
        onLoad() {  

        },  
        methods: {  
            onClick() {  
                this.showTest = !this.showTest;  
            },  
        }  
    });  
</script>  

<style>  
    .content {  
        display: flex;  
        flex-direction: column;  
        align-items: center;  
        justify-content: center;  
    }  

    .logo {  
        height: 200rpx;  
        width: 200rpx;  
        margin: 200rpx auto 50rpx auto;  
    }  

    .text-area {  
        display: flex;  
        justify-content: center;  
    }  

    .title {  
        font-size: 36rpx;  
        color: #8f8f94;  
    }  
</style>

test.vue 代码

<template>  
  <text class="test">hahaha</text>  
</template>  
<script lang="ts">  
import Vue from 'vue';  

export default Vue.extend({  
  data() {  
    return {  
      observer: null,  
    } as {  
      observer: UniApp.IntersectionObserver | null;  
    };  
  },  
  created() {  
    this.createObserver(() => {}, 'test');  
  },  
  destroyed() {  
    this.disconnectObserver();  
  },  
  methods: {  
    createObserver(cb: { (): Promise<void> | void; (): void; }, calssName: string) {  
      this.$nextTick(() => {  
        this.disconnectObserver();  
        this.observer = uni.createIntersectionObserver(this).relativeToViewport({ bottom: -100 }); // 底部有导航栏覆盖,这里从导航栏往上设置可视区域  
        this.observer.observe(calssName, (res) => {  
          if (res.intersectionRatio === 0) {  
            return;  
          }  
          cb();  
          this.disconnectObserver(); // 出现后关闭监听  
        });  
      });  
    },  
    disconnectObserver() {  
      if (this.observer) {  
        console.log('----- disconnectObserver -----');  
        this.observer.disconnect();  
        this.observer = null;  
      }  
    }  
  }  
});  
</script>

操作步骤:

第一步

使用 dcloudio/uni-preset-vue 模板创建一个应用,然后创建一个组件,在组件的 created 生命周期调用 uni.createIntersectionObserver 创建元素的监听器,然后在 destroyed 生命周期调用 disconnect 进行监听器的释放,外部通过 v-if 控制组件的创建与销毁。

示例代码已经放在附件中

第二步

在项目一开始运行时使用开发者工具进行内存快照,在多次创建和销毁带有 IntersectionObserver 相关代码的组件后,再进行一次内存快照,对比两份内存快照,观察 VueComponent 是否存在泄漏的情况。

预期结果:

不应该出现 VueComponent Constructor 内存泄漏,内存中 VueComponent Constructor 的个数应该保持稳定不会无限制增长。

实际结果:

测试组件没有被正确释放,观察内存快照对比,VueComponent Constructor 数量不断上涨

bug描述:

猜测是 disconnect 函数触发以后 observer 的回调函数仍然被其它对象持有导致无法释放,进一步导致组件无法被释放。

补充微信原生小程序对应的使用 createIntersectionObserver 的 demo memory_test_2,通过观察内存分析中的 TestClass ,没有内存泄漏的情况。

2024-07-18 15:23 负责人:无 分享
已邀请:
DCloud_UNI_yuhe

DCloud_UNI_yuhe

感谢反馈,我们会研究一下的

  • l***@gmail.com (作者)

    我还怀疑过是不是小程序底层的问题,从我新上传的 demo 来看,小程序底层看起来没有内存泄漏的问题,辛苦大佬排查一下看看。

    2024-07-18 16:23

飞翔的青蛙

飞翔的青蛙

我这页面中有很多自定义组件时,通过relaunch跳转子包页面就会卡很久很久

在执行this.$vm && this.$vm.$destroy()一直在等待销毁,这一段貌似是uniapp框架内部的代码,销毁完成后都几十秒了

要回复问题请先登录注册