#6 阻止和重啓路由

英文原版:https://guides.emberjs.com/v2.13.0/routing/preventing-and-retrying-transitions/

在路由轉換期間,Ember Router會把一個transition對象傳入route中每一個被調用的鉤子函數。任何一個鉤子都可以通過與此transiton對象交互,並使用transition.abort()方法來立即終止當前的transition;並且如果這個transition對象被暫存了,那麼未來它可以通過調用transition.retry()被再次重啓。

使用willTransition阻止Transition

當試圖發起一個transition時,不論是通過{{link-to}}助手,tansitionTo()還是URL,都會在被訪問的路由中觸發一個叫做willTransition的action函數。這就引起在當前路由路徑上的每一個路由都有機會決定這個transition行爲是否會發生。

想象一下,在你的app中的某一個路由顯示了一個比較複雜的表單,它需要被用戶全部填滿,可是在用戶填寫的過程中突然訪問了上一個頁面。除非這個transition被阻止,否則用戶可能會丟失填寫在表單上的所有數據,這帶來了相當糟糕的用戶體驗。

下面是一種可以解決這種情況的方式:

app/routes/form.js

import Ember from 'ember';

export default Ember.Route.extend({
  actions: {
    willTransition(transition) {
      if (this.controller.get('userHasEnteredData') &&
          !confirm('Are you sure you want to abandon progress?')) {
        transition.abort();
      } else {
        // Bubble the `willTransition` action so that
        // parent routes can decide whether or not to abort.
        return true;
      }
    }
  }
});

上例表示,當用戶點擊一個{{link-to}}助手,或者app在初始化的時候使用transitionTo()方法執行了一個transition,那麼這個transition將會被終止,並且URL將不會變化,同時會彈出對話框。然而,如果通過瀏覽器的後退按鈕離開了form路由,或者用戶手動的改變了URL,那麼這時候網址的改變會在willTransition action被調用前發生。這就使得瀏覽器會顯示這個新的url對應的頁面,就算在willTransition中調用了transition.abort()也是無效的。

通過model,beforeModel和afterModel來終止Transition

model,beforeModel和afterModel在異步路由中有相關描述,並且在它們被調用時都伴隨一個transition對象。這將使目標路由有終止transition的可能。

app/routes/disco.js

import Ember from 'ember';

export default Ember.Route.extend({
  beforeModel(transition) {
    if (new Date() > new Date('January 1, 1980')) {
      alert('Sorry, you need a time machine to enter this route.');
      transition.abort();
    }
  }
});

暫存和重啓Transition

被終止的transition可以在未來被重啓。一個常見情況是,有個驗證路由它的重定向是去登錄頁,並且在用戶登錄成功後再返回到驗證路由。

app/routes/some-authenticated.js

import Ember from 'ember';

export default Ember.Route.extend({
  beforeModel(transition) {
    if (!this.controllerFor('auth').get('userIsLoggedIn')) {
      let loginController = this.controllerFor('login');
      loginController.set('previousTransition', transition);
      this.transitionTo('login');
    }
  }
});
app/controllers/login.js

import Ember from 'ember';

export default Ember.Controller.extend({
  actions: {
    login() {
      // Log the user in, then reattempt previous transition if it exists.
      let previousTransition = this.get('previousTransition');
      if (previousTransition) {
        this.set('previousTransition', null);
        previousTransition.retry();
      } else {
        // Default back to homepage
        this.transitionToRoute('index');
      }
    }
  }
});

本節完

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章