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

关于subNvue的创建与销毁

分类:uni-app

subNvue的创建

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

subNvue的生命周期

在宿主页面创建时,subNvue的生命周期会依次执行,如onLoad\onMounted\onShow\onReady;
当宿主页面销毁时,剩下的如onUnmounted\onUnload也会依次执行。

值得一提的是,由于subNvue并非页面,即使返回打开,其onShow也只会在初始化时执行一次,如果想要监听其出现和隐藏的事件,可以利用其webview的性质,通过plus.webview.getWebviewById获取到势力,而后添加监听事件,例如:

const webView = plus.webview.getWebviewById(id);  
webView.addEventListener('show', doSomething);  
webView.addEventListener('hide', doSomething);

subNvue的销毁

从官方文档和社区了解到,官方并未给出明确的销毁方法,而是只提供了隐藏方法,然而实践下来,依然可以利用其webview的性质调用close方法进行销毁,不过这种方式官方并不推荐。

经过实践,subNvue的创建与销毁,是与其宿主界面强绑定的,宿主界面创建,它也创建,宿主界面销毁,它也自动销毁(宿主是tabbar的除外),大部分情况下是无需手动销毁的。

然而,上面的规律只对二级界面有效,对于一些寄宿在tabbar页面内的subNvue,其销毁就不知为何无法执行了。

当你多次创建tabbar界面(如reLaunch应用后重进tabbar),那个页面包含的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的onLoad或onReady里执行。

值得注意的是,如果我们在父页面销毁前统一销毁子窗口,之后再打开任意subNvue,都会导致navigateBack连续触发两次的bug,原因不明。

0 关注 分享

要回复文章请先登录注册