在路由的轉(zhuǎn)換過(guò)程中,Ember路由器會(huì)通過(guò)回調(diào)(beforeModel
、model
、afterModel
、redirect
)解析一個(gè)transition
對(duì)象到轉(zhuǎn)換的下一路由中。任何一個(gè)回調(diào)都可以通過(guò)傳遞過(guò)來(lái)的transition
參數(shù)獲取transition
對(duì)象,然后使用這個(gè)對(duì)象調(diào)用transition.abort()
方法立即終止路由的轉(zhuǎn)換,如果你的程序保存了這個(gè)對(duì)象(transition
對(duì)象)之后你還可以在需要的地方取出來(lái)并調(diào)用transition.retry()
方法激活路由轉(zhuǎn)換這個(gè)動(dòng)作,最終實(shí)現(xiàn)路由的轉(zhuǎn)換。
當(dāng)用戶通過(guò){{link-to}}
助手、transition
方法或者直接執(zhí)行URL來(lái)轉(zhuǎn)換路由,當(dāng)前路由會(huì)自動(dòng)執(zhí)行willTransition
方法。每個(gè)活動(dòng)的路由都可以決定是否執(zhí)行轉(zhuǎn)換路由。
想象一下,在當(dāng)前路由所渲染的頁(yè)面是一個(gè)比較復(fù)雜的表單,并且用戶已經(jīng)填寫了很多信息,但是用戶很可能無(wú)意中點(diǎn)擊了返回或者關(guān)閉頁(yè)面,這就導(dǎo)致了用戶填寫的信息直接丟失了,這樣的用戶體驗(yàn)并不好。此時(shí)我們可以通過(guò)使用willTransition
方法阻止用戶的行為并提示用戶是否確認(rèn)離開本頁(yè)面。
為了驗(yàn)證這個(gè)特性我們需要?jiǎng)?chuàng)建好測(cè)試所需的文件。
ember g controller form
ember g route form
首先在controller
增加測(cè)試數(shù)據(jù)。
// app/controllers/form.js
import Ember from 'ember';
export default Ember.Controller.extend({
firstName: 'chen',
lastName: 'ubuntuvim'
});
再創(chuàng)建一個(gè)模擬用戶填寫信息的模板。
<div class="form-group">
FirstName
{{input type="text" class="form-control" id="exampleInputEmail1" placeholder="FirstName" value=firstName}}
</div>
<div class="form-group">
LashName
{{input type="text" class="form-control" id="exampleInputPassword1" placeholder="LashName" value=lastName}}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<br><br>
{{#link-to 'about'}}<b>轉(zhuǎn)到about</b>{{/link-to}}
關(guān)鍵部分來(lái)了,我們?cè)诼酚衫锾砑?code>willTransition方法。
// app/routes/form.js
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
willTransition: function(transition) {
// 如果是使用this.get('key')獲取不了頁(yè)面輸入值,因?yàn)椴皇峭ㄟ^(guò)action提交表單的
var v = this.controller.get('firstName');
// 任意獲取一個(gè)作為判斷表單輸入值
if (v && !confirm("你確定要離開這個(gè)頁(yè)面嗎??")) {
transition.abort();
} else {
return true;
}
}
}
});
運(yùn)行:http://localhost:4200/form,先點(diǎn)擊submit
提交表單,可以看到表單順利提交沒(méi)有任何問(wèn)題,然后再點(diǎn)擊轉(zhuǎn)到about
,你可以看到會(huì)彈出如下提示框。
接著,點(diǎn)擊“取消”頁(yè)面沒(méi)有跳轉(zhuǎn),如果是點(diǎn)擊“確定”頁(yè)面會(huì)跳轉(zhuǎn)到about
頁(yè)面。
再接著,把FirstName
這個(gè)輸入框的內(nèi)容清空然后點(diǎn)擊“轉(zhuǎn)到about”頁(yè)面直接跳轉(zhuǎn)到了about
頁(yè)面。
很多博客網(wǎng)站都是有這個(gè)功能的!!
beforeModel(transition) {
if (new Date() > new Date('January 1, 1980')) {
alert('Sorry, you need a time machine to enter this route.');
transition.abort();
}
}
這段代碼演示的就是在beforeModel
回調(diào)中使用abort
方法阻止路由的轉(zhuǎn)換。代碼比較簡(jiǎn)單我就不做例子演示了!
對(duì)于使用abort
方法終止的路由可以調(diào)用retry
方法重新激活。一個(gè)很典型的例子就是登陸。如果登陸成功就轉(zhuǎn)到首頁(yè),否則跳轉(zhuǎn)回登陸頁(yè)面。
文件準(zhǔn)備工作:
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() {
// 獲取跳轉(zhuǎn)過(guò)來(lái)之前路由中設(shè)置的transition對(duì)象
var transitionObj = this.get('transitionObj');
console.log('transitionObj = ' + transitionObj);
if (transitionObj) {
this.set("transitionObj", null);
transitionObj.retry();
} else {
// 轉(zhuǎn)回首頁(yè)
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設(shè)置了userIsLogin為false,默認(rèn)是未登錄
if (!this.controllerFor("auth").get('userIsLogin')) {
var loginController = this.controllerFor("login");
// 保存transition對(duì)象
loginController.set("transitionObj", transition);
this.transitionTo("login"); // 跳轉(zhuǎn)到路由login
}
}
});
這個(gè)是登陸頁(yè)面
login
頁(yè)面,結(jié)果顯示如下:
可以看到URL確實(shí)是轉(zhuǎn)到login
了。
transitionObj
是undefined
。由于沒(méi)有經(jīng)auth
這個(gè)路由的跳轉(zhuǎn)所以獲取不到transition
對(duì)象。自然就跳轉(zhuǎn)回index
這個(gè)路由。
博文完整代碼放在Github(博文經(jīng)過(guò)多次修改,博文上的代碼與github代碼可能又出入,不過(guò)影響不大!),如果你覺(jué)得博文對(duì)你有點(diǎn)用,請(qǐng)?jiān)趃ithub項(xiàng)目上給我點(diǎn)個(gè)star
吧。您的肯定對(duì)我來(lái)說(shuō)是最大的動(dòng)力??!
更多建議: