Ember.js 入門指南——路由切換的防止和重試
在路由的切換過程中,Ember路由器會通過回撥(beforeModel、model、afterModel、redirect)解析一個transition物件到切換的下一路由中。任何一個回撥都可以通過傳遞過來的transition引數獲取transition物件,然後使用這個物件呼叫transition.abort()方法立即終止路由的切換,如果你的程式儲存了這個物件(transition物件)之後你還可以在需要的地方取出來並呼叫transition.retry()方法啟用路由切換這個動作,最終實現路由的切換。
1,通過呼叫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,在beforeModel、model、afterModel回撥中阻止路由切換
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,你會發現頁面直接跳轉到首頁,瀏覽器控制檯列印的transitionObj是undefined。由於沒有經auth這個路由的跳轉所以獲取不到transition物件。自然就跳轉回index這個路由。