在应用中使用路由(Routing)
在一般的网友中, 点击一个link转到一个新的页面。 但是在单页面的应用中,不会载入新页面,只是和当前页面的组件交互。如何使用浏览器的前进/后退功能,就是 Ext Js5开始的路由功能了。
路由可以追踪应用的浏览器历史记录,可以可以直接链接到应用中的某个部分。这对于将app加到书签和发送连接的场景非常有用。
但是路由不能保存数据和 Session,数据需要存储在类似cookie或是本地存储中。路由仅用来追踪应用的状态。
哈希
https://www.example.com/apps/users#user=1234
#user=1234称作哈希。
哈希变化的时候, 浏览器会添加到历史记录。可以使用前进\后退按钮。
应用路由的实现方式
Router类是在Ext JS 5中新增的, 用它来处理应用中的哈希变化。Ext.util.History用来配合哈希的变化。路由是与哈希匹配的字符串,允许在Ext应用程序中进行深层链接。看一个实例:
Ext.define('MyApp.view.main.MainController', {
extend : 'Ext.app.ViewController',
routes : {
'users' : 'onUsers'
},
onUsers : function () {
//...
}
});
这个路由会响应#users哈希, 并且执行onUsers方法。
更新哈希
控制器有提供redirectTo方法来更新哈希。
this.redirectTo(‘user/1234’);
redirectTo还可以设置选项:
force -如果为true,即使地址栏中的哈希值与传递给redirectTo的哈希值相同,这也会强制路由器做出反应。
replace -默认情况下,将更改散列并创建浏览器历史记录中的新条目。 这意味着浏览器的后退按钮可以返回到前一个哈希。 如果为true,则浏览器历史记录中的当前条目将替换为传递给redirectTo的哈希。
默认令牌-Token
在/app/view/Application.js添加defaultToken配置
Ext.define('MyApp.Application', {
extend : 'Ext.app.Application',
//...
defaultToken : 'home'
});
这里会使用#home
启动应用程序时,它将检查URI的当前哈希值。 如果定义了哈希,它将执行路由处理程序。 如果没有找到散列,它将添加#home散列,并且将执行任何路由处理程序以适当地处理它。
带参数的哈希
Ext.define('Extjs6App.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
routes : {
'user/:id' : 'onUser'
},
onItemSelected: function (sender, record) {
Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this);
},
onConfirm: function (choice) {
if (choice === 'yes') {
//
}
},
onUser: function(id){
Ext.Msg.alert('Route', 'routes is user/'+id);
}
});
在控制器中加入routes, 在浏览器输入 http://localhost:1841/#user/1234, 效果就是会弹出对话框。
最重要的效果是如果输入http://localhost:1841/#user/12345 之后, 可以使用浏览器的后退按钮回到之前的页面了。
哈希参数的格式
使用conditions设置参数的格式:
Ext.define('MyApp.view.main.MainController', {
extend : 'Ext.app.ViewController',
routes : {
'user/:id' : {
action : 'onUser',
conditions : {
':id' : '([0-9]+)'
}
}
},
onUser : function (id) {
//...
}
});
路由的处理
有时候需要阻止路由的处理。比如当前用户是否有权限查看应用程序的某些部分。可以配置before 用来停止当前或所有路由, 或者继续执行。
Ext.define('MyApp.view.main.MainController', {
extend : 'Ext.app.ViewController',
routes : {
'user/:id' : {
before : 'onBeforeUser',
action : 'onUser'
}
},
onBeforeUser : function (id, action) {
Ext.Ajax.request({
url : '/security/user/' + id,
success : function() {
action.resume();
}
});
},
onUser : function (id) {
//...
}
});
onBeforeUser的一个参数是id , 第二个参数是 action, 执行 action的 resume方法继续执行。停止路由,
onBeforeUser : function (id, action) {
Ext.Ajax.request({
url : '/security/user/' + id,
success : function () {
action.resume();
},
failure : function () {
action.stop();
}
});
},
处理没有匹配的路由
如果修改哈希没有找到对应的路由, 就会触发unmatchedroute?事件
Ext.application({
name : 'MyApp',
listen : {
controller : {
'#' : {
unmatchedroute : 'onUnmatchedRoute'
}
}
},
onUnmatchedRoute : function (hash) {
//...
}
});
也可以触发一个全局的事件:
Ext.application({
name : 'MyApp',
listen : {
global : {
unmatchedroute : 'onUnmatchedRoute'
}
},
onUnmatchedRoute : function (hash) {
//...
}
});
还可以直接使用 Ext的事件
Ext.on('unmatchedroute', function (hash) {
//...
});
在单个哈希使用多个路由
使用管道分割符: |
#user/1234|messages
就会同时执行两个路由了。
这个默认分割符也可以通过Ext.route.Router.multipleToken修改。
路由的名字也可以修改
routes: {
'bar' : 'onBar',
'baz' : {
action : 'onBaz',
name : 'bazRoute'
},
'foo' : 'onFoo'
}
初始哈希可以通过首先传递一个字符串来设置
this.redirectTo(‘foo’);
如果再加一个的话
this.redirectTo({
bar : 'bar'
});
就是叠加了, 哈希是#foo|bar.
如果已存在的就是替换
this.redirectTo({
foo : 'foober'
});
变成: ?#foober|bar
Hashbang?的支持
Hashbang?会在#之后多一个 !
设置方式 Ext.util.History.hashbang = true;
在
Ext.application({
name : 'MyApp',
router : {
hashbang : true
}
});
也可以这样设置:
Ext.route.Router.setHashbang(true);
暂停和恢复路由
一个常见的用例是在应用程序启动时延迟执行路由,直到用户检验完成。
Ext.application({
name : 'MyApp',
defaultToken : 'home',
launch : function () {
var me = this;
Ext.route.Router.suspend();
me
.checkUserSession()
.then(me.onUser.bind(me), me.onUserError.bind(me));
},
onUser : function (user) {
MyApp.$user = user;
Ext.route.Router.resume();
},
onUserError : function (error) {
// handle error
// do not execute queued hash changes
Ext.route.Router.resume(true);
this.redirectTo('login');
}
});