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 个评论
要回复文章请先登录或注册