ionViewWillEnter vs ionViewDidEnter

时间:2017-09-25 13:19:51

标签: angular typescript ionic-framework ionic2 ionic3

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

现在,让我们假设我们每次进入视图时都需要执行任务,我们如何选择使用ionViewWillEnterionViewDidEnter

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

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

附加说明:
我注意到寻找一个明确写在离子文档中的答案。如果放入ionViewWillEnter vs ionViewDidEnter

,我打算知道的是什么是利弊

例如:在ionViewDidEnter中发起会导致一些延迟(例如,我不确定) - 即使是微不足道的

3 个答案:

答案 0 :(得分:43)

sebaferreras answer很棒,但缺少一些观点。

 首先,关于ionic life cycle。如果您记下所有离子事件并在每个事件中加上console.log,您将看到该场景:

constructor --> ionViewDidLoad --> ionViewWillEnter --> ionViewDidEnter --> ionViewWillLeave --> ionViewDidLeave --> ionViewWillUnload.
页面启动时,

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")
}

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

答案 1 :(得分:9)

答案很简单,一如既往,了解幕后情况的最佳方法是检查Ionic的源代码。

长话短说: ionViewWillEnter生命周期挂钩在页面转换开始之前触发,ionViewDidEnter在转换完成后触发。请查看本答案的结尾,以查看对源代码的引用。

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

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

  • 当您因某种原因需要与DOM交互时也是如此,因为在执行IonViewWillEnter时已经加载了DOM,因此这可以帮助您尽快初始化页面一点点运气,页面可以显示给用户准备好使用

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

那么什么时候应该使用ionViewDidEnter呢?

  • 我注意到有时在非常老的Android设备上执行应用程序(小于512mb - 1gb RAM)时,在向API发出请求时动画可能有点滞后。 ionViewWillEnter,因此最好在ionViewDidEnter向API发出这些请求,以确保动画完成

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

您可以查看 NavControllerBase code

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));

   // ...

}

和...

  // 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);
      });
    }
  }

如果您从beforeAddRead定义中检查animation.d.ts方法,您会看到:

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

现在我们可以确保在页面转换开始之前执行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);
      }

      // ..

    }

    // ...

  }

并且

// 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);
    }
  }

因此,我们可以说转换完成后会触发 ionViewDidEnter生命周期挂钩。

答案 2 :(得分:0)

如果要在显示视图之前执行任务,请使用 ionViewWillEnter 。 如果您想在查看视图后执行任务,请使用 ionViewDidEnter

这完全取决于场景。例如,如果要在显示视图之前更改ui元素的属性,请使用ionViewWillEnter。在你的问题的例子中:4)在DOM元素完全加载后启动一些东西(例如:google map init。所以在这种情况下你可以使用ionViewDidEnter