5***@qq.com
5***@qq.com
  • 发布:2025-05-06 17:01
  • 更新:2025-05-06 17:01
  • 阅读:22

关于subNvue的创建与销毁

分类:uni-app

subNvue的创建
subNvue作为vue或nvue页面的原生子窗体,当其父页面创建时,subNvue也随之创建,且仅创建一次,其生命周期也只会触发一次(包括onShow)。

subNvue的销毁
官方只提供了隐藏方法,并未提供销毁方法,目前看只有在退出APP即杀死应用的时候,才会跟着APP进程一并消失。

结合上面两条规律,一旦你对某个包含subNvue的页面进行了多次创建(如uni.reLaunch),那个页面包含的subNvue也会随之多次创建,并保留在内存里。
通过调用 plus.webview.all()方法,在返回的webview列表里,你可以看到多个id相同但是 __uniapp_origin_id(父页面的id)不同的subNvue,这也就导致了几个问题:

  • 当你想要通过getSubNVueById方法获取子窗体实例时,你获取到的可能并不是最新的实例,一旦你的子窗体有动态元素,最终渲染出的窗口也大概率是旧内容。
  • 当你想要隐藏某个窗口时,情况也差不多,你无法精准拿到目前在界面上显示的子窗口实例,hide方法虽然执行了,但具体是哪个实例在执行,你也不知道。
  • 所有旧的subNvue都会保存在内存里,即使父页面销毁也依然存留,无疑会增加性能消耗。

所幸,webview提供了close方法,我们可以筛选出id重复的subNvue,通过__uniapp_origin_id进行排序(新创建的页面,其id是递增的),之后手动清理即可。

const clearOldSubNvue = (id) => {  
  const webview = plus.webview  
    .all()  
    .filter((view) => view.id === id)  
    .sort((a, b) => +a.__uniapp_origin_id - +b.__uniapp_origin_id);  

  if (webview.length <= 1) return;  

  webview.forEach((view, index) => {  
    if (index < webview.length - 1) {  
      view.close();  
    }  
  });  
};

值得注意的是,如果我们在父页面销毁前统一销毁子窗口,之后再打开任意subNvue,都会导致navigateBack连续触发两次的bug,因此建议在父页面的onLoad方法里调用清理函数,麻烦,但好在管用。

0 关注 分享

要回复文章请先登录注册