1. 程式人生 > >Ember.js 入門指南——路由切換的防止和重試

Ember.js 入門指南——路由切換的防止和重試

    在路由的切換過程中,Ember路由器會通過回撥(beforeModelmodelafterModelredirect)解析一個transition物件到切換的下一路由中。任何一個回撥都可以通過傳遞過來的transition引數獲取transition物件,然後使用這個物件呼叫transition.abort()方法立即終止路由的切換,如果你的程式儲存了這個物件(transition物件)之後你還可以在需要的地方取出來並呼叫transition.retry()方法啟用路由切換這個動作,最終實現路由的切換。

1,通過呼叫willTransition方法阻止路由切換

       當用戶通過

{{link-to}}助手、transition方法或者直接執行URL來切換路由,當前路由會自動執行willTransition方法。每個活動的路由都可以決定是否執行切換路由。

       想象一下,在當前路由所渲染的頁面是一個比較複雜的表單,並且使用者已經填寫了很多資訊,但是使用者很可能無意中點選了返回或者關閉頁面,這就導致了使用者填寫的資訊直接丟失了,這樣的使用者體驗並不好。此時我們可以通過使用willTransition方法阻止使用者的行為並提示使用者是否確認離開本頁面。

       為了驗證這個特性我們需要建立好測試所需的檔案。

       ember g controller form

       ember g route form

首先在controller增加測試資料。

//  app/controllers/form.js
 
import Ember from 'ember';
 
export default Ember.Controller.extend({
       firstName: 'chen',
       lastName: 'ubuntuvim'
});

再建立一個模擬使用者填寫資訊的模板。

<form>
  <div>
    <label for="exampleInputEmail1">FirstName</label>
    {{input type="text" id="exampleInputEmail1" placeholder="FirstName" value=firstName}}
  </div>
  <div>
    <label for="exampleInputPassword1">LashName</label>
    {{input type="text" id="exampleInputPassword1" placeholder="LashName" value=lastName}}
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
 
<br><br>
{{#link-to 'about'}}<b>轉到about</b>{{/link-to}}

關鍵部分來了,我們在路由裡新增willTransition方法。

//  app/routes/form.js
 
import Ember from 'ember';
 
export default Ember.Route.extend({
       actions: {
           willTransition: function(transition) {
                 //  如果是使用this.get('key')獲取不了頁面輸入值,因為不是通過action提交表單的
                 var v = this.controller.get('firstName');
                 //  任意獲取一個作為判斷表單輸入值
               if (v && !confirm("你確定要離開這個頁面嗎??")) {
                   transition.abort();
               } else {
                   return true;
               }
           }
       }
});

       執行:http://localhost:4200/form,先點選“submit”提交表單,可以看到表單順利提交沒有任何問題,然後再點選轉到about”,你可以看到會彈出如下提示框。

接著,點選取消頁面沒有跳轉,如果是點選確定頁面會跳轉到about頁面。

再接著,把FirstName輸入框的內容清空然後點到about”面直接跳到了about面。

       很多部落格網站都是有這個功能的!!

2,在beforeModelmodelafterModel回撥中阻止路由切換

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

       這段程式碼演示的就是在beforeModel回撥中使用abort方法阻止路由的切換。程式碼比較簡單我就不做例子演示了!

3儲存transition物件、路由切換重試

       對於使用abort方法終止的路由可以呼叫retry方法重新啟用。一個很典型的例子就是登陸。如果登陸成功就轉到首頁,否則跳轉回登陸頁面。

檔案準備工作:

ember g controller auth

ember g route auth

ember g controller login

ember g route login

       下面是演示用到的程式碼。

//  app/controllers/login.js
 
import Ember from 'ember';
 
export default Ember.Controller.extend({
       actions: {
              login: function() {
          //  獲取跳轉過來之前路由中設定的transition物件
                     var transitionObj = this.get('transitionObj');
                     console.log('transitionObj = ' + transitionObj);
                     if (transitionObj) {
                            this.set("transitionObj", null);
                            transitionObj.retry();
                     } else {
                            //  轉回首頁
                            this.transitionToRoute('index');
                     }
              }
       }
});
//  app/controllers/auth.js
 
import Ember from 'ember';
 
export default Ember.Controller.extend({
       userIsLogin: false
});
//  app/routes/auth.js
 
import Ember from 'ember';
 
export default Ember.Route.extend({
       beforeModel(transition) {
              // 在名為auth的controller設定了userIsLogin為false,預設是未登入
              if (!this.controllerFor("auth").get('userIsLogin')) {
                     var loginController = this.controllerFor("login");
                     // 儲存transition物件
                     loginController.set("transitionObj", transition);
                     this.transitionTo("login");  // 跳轉到路由login
              }
       }
});
<!--  //app/templates/login.hbs -->
 
這個是登陸頁面

可以看到URL確實是轉到login了。

2,執行http://localhost:4200/login,你會發現頁面直接跳轉到首頁,瀏覽器控制檯列印的transitionObjundefined。由於沒有經auth這個路由的跳轉所以獲取不到transition物件。自然就跳轉回index這個路由。