ionicView视图的生命周期

时间:2022-06-26 04:38:32

此文章转载自同事的wiki,因为觉得对结合理解栈和视图很有帮助,就分享给更多的朋友,如果有错误的地方,欢迎指出!

在看ionicview视图的生命周期前面,我希望大家可以先了解一下栈这个概念。我所能理解的栈,即一种先进后出的模式。这个时候我们把栈和视图联系起来,就可以很好的理解。

一、页面跳转

  • A->B->C->D

你首先进入A页面,这个时候A页面处于栈顶的位置,然后这个时候从A页面跳到B页面,B页面进栈,B页面就处在栈顶,同理C页面和D页面都一样。最后的结果是栈顶为D页面,其次为C、B、A。

  • A->B->C->D->A

首先A->B->C->D和上面一样,这个时候你要从D页面去A页面,这里就要分为2种方式来区分:

方式1,使用跳转的方式:比如说常用的$state.go和$location.path,这里我拿$state.go来介绍。当你使用$state.go进入A页面,首先会先在栈中查找A页面:

  • 如果A页面已经在栈中存在了,它就会从栈中帮A页面取出来移到栈顶,这个时候栈的顺序就为栈顶为A页面,其次为D、C、B;
  • 如果A页面在栈中不存在的话,这个时候A页面是一个新的页面,它就会进栈,成为栈顶。

方式2,使用返回的方式:我们经常用的history.goback(),返回到上一页,其实它是在执行这么一个过程:history.goback(-1),让当前页面出栈,移出这个栈,让上一个页面成为栈顶。这里的-1就是返回到上一个页面,同理-2就代表着返回到上上个页面,你从D页面去A页面的话要是采用history.goback(),那么其实你是在执行:首先D页面出栈,C页面成为栈顶,然后C页面出栈,B页面变为栈顶,最后B页面出栈,返回到A页面,A页面成为栈顶,此时的栈中也就只有A了。那么history.goback()里面的参数,就是你要返回页面的下标与当前页面的下标差值。

那么这里的下标什么意思呢? 
所谓下标,我们经常在数组中听到,那么其实这个栈我们也可以理解为一个存放页面视图的数组,

ionic中是这样表示的:

  • var historyId = $ionicHistory.currentHistoryId(); 
    这里的historyId 代表是属于哪个栈里面的,根据historyId 来标识栈。 
    因为这里存在2个标识: 
    1,单独登录页面栈 
    2,除登陆页面以外的所有页面的栈
  • var history = $ionicHistory.viewHistory().histories[historyId]; 
    这里的history 代表是根据historyId 来找到history 历史记录
  • history.stack 数组 
    这里的history.stack代表history 的栈,它是一个数组

至此我们已经得到了history.stack数组,接着我们根据history.stack[i].stateName和页面路由配置里的name相比较,很容易就得到页面在数组里面的下标,至此即可返回到A页面。

二、在页面跳转的同时,我们不可避免的要与缓存打交道,缓存不能说好,也不能说不好,关键在于我们怎么利用。我们可以做到什么时候想让一个页面有缓存,什么时候让一个页面没有缓存,那么怎么能做到这样呢?

这个时候我们拿上面例子,方式1中A页面已存在来说:(PS:默认所有页面都是缓存数据的)

当你从D页面跳到A页面,这个时候你在A页面再跳到B页面,同理A页面的跳转,这个时候B页面移到栈顶,此时栈的顺序为B、A、D、C,这个时候B页面存在缓存数据,但是按照正常的逻辑,B页面在从A页面跳过来的时候是不想要缓存数据的,那么如何解决处理B页面的缓存数据呢?可能你会说设置B页面的路由为cache=false即可不缓存数据,这样是可以,但是如果我要是正常A->B->C->D 从C页面返回B页面是想要缓存数据的,由于设置了cache=false,就不会有缓存数据了,这就不符合业务逻辑啦。所以在你从D页面回A页面的时候不要采用方式1,而是采用方式2,那么就可以完成D->A->B,B页面不存在缓存数据。

由此可得,如果你要想实现从一个页面跳到一个已经存在的页面,比如 A->B->C->D->A 你想回到A,而不想缓存B或C、D页面,那么你就使用方式2,其它情况可以使用方式1。

三、页面跳转,离不开页面,谈到页面我们就需要谈一谈视图的生命周期(PS:这里我同原生activity进行比较,毕竟有比较才会有收获)

ionic view   android activity
loaded < ——对应——> onCreate (创建)
beforeEnter    
enter < ——对应——> onStart (用户看见了界面)
afterEnter < ——对应——> onResume(用户得到了界面焦点)
beforeLeave < ——对应——> onPause (用户失去了界面焦点)
leave < ——对应——> onStop (用户看不见了界面)
afterLeave    
unloaded < ——对应——> onDestroy (销毁)
    onRestart (再一次回到这个界面)


如果你进入一个栈中不存在的页面,比如A->B->C,这个时候你进入D页面, 
D页面:loaded->beforeEnter->enter->afterEnter, 这个时候代表着D页面已经完全展现在用户面前;即D进入栈中,D处于栈顶

假设1:我们这个时候从D页面返回到C页面, 
D页面:beforeLeave->leave->afterLeave->unloaded, 这个时候代表着D页面已经消失在用户面前;即D已经离开栈

假设2:我们这个时候从D页面跳到新的界面E, 
D页面:beforeLeave->leave->afterLeave, 这个时候代表着D页面只是暂时消失在用户面前;即D不处于栈顶,但还在栈内

假设3:我们这个时候从界面E返回界面D, 
D页面:beforeEnter->enter->afterEnter, 这个时候代表着D页面又出现在用户面前;即D又处于栈顶

假设4:如果这个时候在D页面按手机的返回键退出程序,生命周期执行同假设1

假设5:如果这个时候在D页面直接按手机的home键,生命周期执行beforeLeave->leave->afterLeave,然后我们再点击app,直接出现D页面,生命周期执行beforeEnter->enter->afterEnter

比较假设1,2,3,4,5;我们可以得出,loaded和unloaded在D页面的生命周期内只执行一次,即第一次进栈和离开栈的时候,如果页面还在栈内,就是围绕着beforeLeave->leave->afterLeave和beforeEnter->enter->afterEnter这几个来进行生命周期。