ionViewWillEnter vs ionViewDidEnter

sta*_*lay 21 typescript ionic-framework ionic2 ionic3 angular

当我们不想重新启动已经缓存的任务时,毫无疑问我们将会使用ionDidLoad.

现在,我们假设我们每次进入视图时都需要执行任务,我们如何在使用ionViewWillEntervs 之间做出选择ionViewDidEnter.

我没有找到任何明确的指导方针.

例如:
1)获取navParams
2)调用REST api
3)声明变量
4)完全加载DOM元素后启动一些东西(例如:google map init)

附加说明:
我注意到要在离子文档中明确写出答案.我打算知道的是,如果放入ionViewWillEntervs, 有什么优点和缺点ionViewDidEnter

例如:启动ionViewDidEnter将导致一些延迟(例如,我不确定这一点) - 即使是微不足道的

Dua*_*nnx 47

sebaferreras 答案很棒,但缺少一些观点.

首先,关于离子生命周期.如果你记下所有离子事件并console.log在每个事件中放入一个,你会看到这个场景:

constructor --> ionViewDidLoad --> ionViewWillEnter --> ionViewDidEnter --> ionViewWillLeave --> ionViewDidLeave --> ionViewWillUnload.
Run Code Online (Sandbox Code Playgroud)

constructor页面启动时首先运行.这是您为变量声明默认值的最佳位置.
ionViewDidLoad视图完全加载时触发.这意味着您可以在此处附加DOM元素.

ionViewWillEnter页面即将进入并成为活动页面时运行. ionViewDidEnter页面完全进入后运行,现在是活动页面. ionViewDidEnter之后,将触发所有 同步ionViewWillEnter完成.为证明这一点,只需将重码放入ionViewWillEnter:

ionViewWillEnter(){
    console.log("ionViewWillEnter")
    for(let i = 0; i < 100000; i++){
      console.log(i);
    }
}
ionViewDidEnter(){
    console.log("ionViewDidEnter")
}
Run Code Online (Sandbox Code Playgroud)

运行您的代码,您将看到启动页面需要很长时间.所以永远不要把重型同步代码放入 ionViewWillEnter.只需使用异步ionViewWillEnter,并将所有的同步代码ionViewDidEnter.因为在那里,您的页面被输入并且它将成为更好的用户体验.

  • _只需在`ionViewWillEnter`中使用异步并将所有同步代码移动到`ionViewDidEnter`_很棒的答案,谢谢你把它带出来:) (6认同)

seb*_*ras 9

答案很简单,一如既往,查看幕后发生的事情的最佳方法是检查Ionic的源代码.

长话短说:ionViewWillEnter生命周期挂钩触发网页过渡开始之前,以及ionViewDidEnter在过渡完成后启动.请查看此答案的结尾,以查看对源代码的引用.

那么,何时应该使用这些钩子?必须有几种可能的场景,所以这些只是基于我所参与的一些应用程序的一些想法.

  • 有时您希望每次用户打开该页面时更新页面上的某些信息; 这可能需要向远程API发出HTTP请求以获取某些数据.在这种情况下,我们可以说使用IonViewWillEnter似乎是正确的选项,因此您可以尽快提出请求,也可以更快地获得响应.

  • 这同样适用于当你需要,因为DOM的时候已经被装入DOM因故交互IonViewWillEnter执行,因此这可以帮助你尽快初始化页面,并与幸运一点点的页面可能向用户显示准备使用.

  • 当您需要使用从上一个视图获得的某些参数初始化视图时,这同样有效.在这种情况下,由于这是一个非常简单的操作,您可以使用ionViewWillEnter生命周期钩子,并且视图将显示已初始化为用户.

所以你ionViewDidEnter什么时候应该使用呢?

  • 我注意到,在很老的Android设备上运行有时候,当应用程序(少于512MB - 1GB RAM),动画可以使在该API的请求时有点滞后ionViewWillEnter,所以它会是一个很好的想要在API中向API发出这些请求以ionViewDidEnter确保动画完成

  • 在某些应用程序中,我被要求在推送页面的元素中包含一些奇特的动画,例如从底部引入部分内容,在延迟后淡化其他一些元素,等等.你可以使用角度动画(为了能够控制时间),避免这些动画的一些延迟的最好方法是使用ionViewDidEnter钩子.这也将使您感觉用户感觉该页面中元素的动画是页面本身过渡的延续.


您可以查看NavControllerBase代码:

1) IonViewWillEnter

// around line 666...
_transitionStart(...): Promise<NavResult> {

    // ...

    // around line 700...

    // create a callback that needs to run within zone
    // that will fire off the willEnter/Leave lifecycle events at the right time
    transition.beforeAddRead(this._viewsWillLifecycles.bind(this, enteringView, leavingView));

   // ...

}
Run Code Online (Sandbox Code Playgroud)

和...

  // around line 805...
  _viewsWillLifecycles(enteringView: ViewController, leavingView: ViewController) {
    if (enteringView || leavingView) {
      this._zone.run(() => {
        // Here, the order is important. WillLeave must be called before WillEnter.
        leavingView && this._willLeave(leavingView, !enteringView);
        enteringView && this._willEnter(enteringView);
      });
    }
  }
Run Code Online (Sandbox Code Playgroud)

如果beforeAddReadanimation.d.ts定义中检查方法,您将看到:

/**
* Add a function which contains DOM reads, which will run
* before the animation begins.
*/
beforeAddRead(domReadFn: Function): Animation;
Run Code Online (Sandbox Code Playgroud)

所以现在我们可以确保在页面转换开始之前ionViewWillEnter执行生命周期钩子

2) IonViewDidEnter

这个有点简单.再次相同NavControllerBase:

// around line 743...
  _transitionFinish(...): NavResult {

    // ...

    // around line 753...
    if (hasCompleted) {
      // transition has completed (went from 0 to 1)
      if (enteringView) {
        enteringName = enteringView.name;
        this._didEnter(enteringView);
      }

      // ..

    }

    // ...

  }
Run Code Online (Sandbox Code Playgroud)

// around line 939...
  _didEnter(view: ViewController) {
    assert(this.isTransitioning(), 'nav controller should be transitioning');
    assert(NgZone.isInAngularZone(), 'callback should be zoned');

    try {
      view._didEnter();
      this.viewDidEnter.emit(view);
      this._app.viewDidEnter.emit(view);
    } catch (e) {
      this._errHandler && this._errHandler.handleError(e);
    }
  }
Run Code Online (Sandbox Code Playgroud)

所以,正因为如此,我们可以说,ionViewDidEnter过渡完成后的生命周期挂钩被触发.