Aurelia 动态加载路由/从获取
Aurelia load routes dynamically / from fetch
我想动态加载菜单选项。所以我想知道最好的方法
我可以使用下面的代码在页面加载后添加路由。这适用于正常导航,但在刷新期间不起作用。
可以配置路由器 return 承诺/如何将菜单项加载到路由中?
@inject(HttpClient)
export class DocumentMenu {
router: Router;
documents : IDocument[];
heading = 'Document Router';
constructor(public http: HttpClient) {}
activate(): void {
this.http.fetch('http://localhost:17853/Document/GetDocuments?folderID=13244')
.then<IDocument[]>(response => response.json())
.then<IDocument[]>(docs => {
if ( docs ){
for( var doc of docs){
this.router.addRoute( { route : doc.DocumentID.toString(), name : doc.Name, moduleId: './documents/document', nav:true, title: doc.Name });
}
this.router.refreshNavigation();
}
return docs;
});
}
configureRouter(config: RouterConfiguration, router: Router) {
var routes = new Array();
routes.push(
{ route: 'index', name: 'index-name', moduleId: './documents/index', nav: false, title: 'Documents' } );
routes.push( { route: '', redirect: 'index' } );
config.map( routes );
this.router = router;
}
}
为了完成这项工作,我在构造函数中使用同步请求创建了路由
export class DocumentMenu {
...
routes : RouteConfig[];
constructor(http: HttpClient) {
this.http = http;
var folderID = window.location.hash.split('/')[2]
this.routes = new Array<RouteConfig>();
this.routes.push ( { route: 'index', name: 'index-name', moduleId: './documents/index', nav: false, title: 'Documents' });
this.routes.push ( { route: '', redirect: 'index' } );
for( var route of this.getRoutes( folderID )){
this.routes.push( route );
}
}
getRoutes(folderID: string) : RouteConfig[]
{
var routes = new Array<RouteConfig>();
var docsURL = 'http://localhost:17853/Document/GetDocuments?folderID=' + folderID;
// synchronous request
var docsResp = $.ajax({
type: "GET",
url: docsURL,
async: false,
cache:false
}).responseText;
var docs = JSON.parse( docsResp );
for( var doc of docs ){
routes.push( { route : doc.DocumentID.toString(), name : doc.Name, moduleId: './documents/document', nav:true, title: doc.Name });
}
return routes;
}
configureRouter(config: RouterConfiguration, router: Router) {
config.map( this.routes );
this.router = router;
}
...
这并没有回答你的问题,但我认为它可能对你和其他有类似问题的人有所帮助。
动态路由反模式
您的应用程序有许多不同的路由,所有这些路由都因应用程序的状态而异。所以必须先fetch数据,然后构建routes,再注册到router。
这是一个反模式的原因是,当 Aurelia 本身是用描述动态内容的静态方式构建时,您将需要根据应用程序的状态不断更新路由器。
动态路由同类数据
假设您正在构建 Google 驱动器,并且您有许多不同的文件,这些文件可能会随着用户添加和删除而改变。对于这种情况,您有两类路由:文件夹和文档。因此,您为每个人制作一条路线。
configureRouter(config) {
config.map([
{ route: 'folder/:id', moduleId: 'folder' }
{ route: 'document/:id', moduleId: 'document' }
}
}
class FolderViewModel {
activate({ id }) {
// get your specific folder data and load it into your folder view model
this.fetch('getDocuments?folderId=${id}')
}
}
class DocumentViewModel {
activate({ id }) {
// get your specific document and load it into your document view model
this.fetch('getDocuments?documentId=${id}')
}
}
动态路由异构数据
假设您想要创建 YouTube。 user mjd10d 登录后,欢迎他随心所欲地观看视频,但他不是高级内容创建者,无法访问网站的内容创建部分。处理此问题的最佳方法是在您的应用程序中保留所有可能的路由,并根据 AuthorizeStep
.
中的用户凭据过滤它们
configureRouter(config, router) {
config.addPipelineStep('authorize', AuthorizeStep);
}
@inject(UserSession)
class AuthorizeStep {
constructor(UserSession) {
this.user = UserSession;
}
run(navigationInstruction, next) {
var instructions = navigationInstruction.getAllInstructions()
if (!this.authorized(instructions.config)) {
return Redirect('404');
}
return next();
}
authorized(routeConfig) {
// something smart that returns false if unauthorized
return this.user.permissionLevel > routeConfig.requiredPermission;
}
}
虽然并非所有情况都与授权相关,但您始终可以使用 addPipelineStep API
注册您自己的管道步骤
您可以通过在 "configureRouter" 方法(在 app.ts 中)中使用单个固定(静态)路由来动态添加路由(在启动时或任何时候),然后添加所有其他路由都是动态的,当你的获取完成时,像这样:
configureRouter(config, router) {
config.title = 'SM';
//configure one static route:
config.map([
{ route: ['', 'welcome'], name: 'welcome', moduleId: 'welcome/welcome', title: 'Welcome' }
]);
routeMaps(this.navRepo) //your repo/service doing the async HTTP fetch, returning a Promise<Array<any>> (i.e., the routes)
.then(r => {
r.forEach(route => this.router.addRoute(route));
//once all dynamic routes are added, refresh navigation:
this.router.refreshNavigation();
});
this.router = router;
}
"routeMaps" 函数只是 repo 调用的包装器以及结果到路由项数组的映射。
您可以return激活承诺。如果 activate() return 是一个承诺,configureRouter() 不会触发,直到 activate() 中的承诺 return 得到解决。
我最终在 activate 中准备了如下路线:
activate(){
return this.http.fetch('url')
.then(response => response.json())
.then(docs => {
this.routerMapped = docs;
});
}
configureRouter(config, router) {
//build the routes from this.routermapped if necessary
config.map( this.routerMapped );
this.router = router;
}
我想动态加载菜单选项。所以我想知道最好的方法
我可以使用下面的代码在页面加载后添加路由。这适用于正常导航,但在刷新期间不起作用。
可以配置路由器 return 承诺/如何将菜单项加载到路由中?
@inject(HttpClient)
export class DocumentMenu {
router: Router;
documents : IDocument[];
heading = 'Document Router';
constructor(public http: HttpClient) {}
activate(): void {
this.http.fetch('http://localhost:17853/Document/GetDocuments?folderID=13244')
.then<IDocument[]>(response => response.json())
.then<IDocument[]>(docs => {
if ( docs ){
for( var doc of docs){
this.router.addRoute( { route : doc.DocumentID.toString(), name : doc.Name, moduleId: './documents/document', nav:true, title: doc.Name });
}
this.router.refreshNavigation();
}
return docs;
});
}
configureRouter(config: RouterConfiguration, router: Router) {
var routes = new Array();
routes.push(
{ route: 'index', name: 'index-name', moduleId: './documents/index', nav: false, title: 'Documents' } );
routes.push( { route: '', redirect: 'index' } );
config.map( routes );
this.router = router;
}
}
为了完成这项工作,我在构造函数中使用同步请求创建了路由
export class DocumentMenu {
...
routes : RouteConfig[];
constructor(http: HttpClient) {
this.http = http;
var folderID = window.location.hash.split('/')[2]
this.routes = new Array<RouteConfig>();
this.routes.push ( { route: 'index', name: 'index-name', moduleId: './documents/index', nav: false, title: 'Documents' });
this.routes.push ( { route: '', redirect: 'index' } );
for( var route of this.getRoutes( folderID )){
this.routes.push( route );
}
}
getRoutes(folderID: string) : RouteConfig[]
{
var routes = new Array<RouteConfig>();
var docsURL = 'http://localhost:17853/Document/GetDocuments?folderID=' + folderID;
// synchronous request
var docsResp = $.ajax({
type: "GET",
url: docsURL,
async: false,
cache:false
}).responseText;
var docs = JSON.parse( docsResp );
for( var doc of docs ){
routes.push( { route : doc.DocumentID.toString(), name : doc.Name, moduleId: './documents/document', nav:true, title: doc.Name });
}
return routes;
}
configureRouter(config: RouterConfiguration, router: Router) {
config.map( this.routes );
this.router = router;
}
...
这并没有回答你的问题,但我认为它可能对你和其他有类似问题的人有所帮助。
动态路由反模式
您的应用程序有许多不同的路由,所有这些路由都因应用程序的状态而异。所以必须先fetch数据,然后构建routes,再注册到router。
这是一个反模式的原因是,当 Aurelia 本身是用描述动态内容的静态方式构建时,您将需要根据应用程序的状态不断更新路由器。
动态路由同类数据
假设您正在构建 Google 驱动器,并且您有许多不同的文件,这些文件可能会随着用户添加和删除而改变。对于这种情况,您有两类路由:文件夹和文档。因此,您为每个人制作一条路线。
configureRouter(config) {
config.map([
{ route: 'folder/:id', moduleId: 'folder' }
{ route: 'document/:id', moduleId: 'document' }
}
}
class FolderViewModel {
activate({ id }) {
// get your specific folder data and load it into your folder view model
this.fetch('getDocuments?folderId=${id}')
}
}
class DocumentViewModel {
activate({ id }) {
// get your specific document and load it into your document view model
this.fetch('getDocuments?documentId=${id}')
}
}
动态路由异构数据
假设您想要创建 YouTube。 user mjd10d 登录后,欢迎他随心所欲地观看视频,但他不是高级内容创建者,无法访问网站的内容创建部分。处理此问题的最佳方法是在您的应用程序中保留所有可能的路由,并根据 AuthorizeStep
.
configureRouter(config, router) {
config.addPipelineStep('authorize', AuthorizeStep);
}
@inject(UserSession)
class AuthorizeStep {
constructor(UserSession) {
this.user = UserSession;
}
run(navigationInstruction, next) {
var instructions = navigationInstruction.getAllInstructions()
if (!this.authorized(instructions.config)) {
return Redirect('404');
}
return next();
}
authorized(routeConfig) {
// something smart that returns false if unauthorized
return this.user.permissionLevel > routeConfig.requiredPermission;
}
}
虽然并非所有情况都与授权相关,但您始终可以使用 addPipelineStep API
注册您自己的管道步骤您可以通过在 "configureRouter" 方法(在 app.ts 中)中使用单个固定(静态)路由来动态添加路由(在启动时或任何时候),然后添加所有其他路由都是动态的,当你的获取完成时,像这样:
configureRouter(config, router) {
config.title = 'SM';
//configure one static route:
config.map([
{ route: ['', 'welcome'], name: 'welcome', moduleId: 'welcome/welcome', title: 'Welcome' }
]);
routeMaps(this.navRepo) //your repo/service doing the async HTTP fetch, returning a Promise<Array<any>> (i.e., the routes)
.then(r => {
r.forEach(route => this.router.addRoute(route));
//once all dynamic routes are added, refresh navigation:
this.router.refreshNavigation();
});
this.router = router;
}
"routeMaps" 函数只是 repo 调用的包装器以及结果到路由项数组的映射。
您可以return激活承诺。如果 activate() return 是一个承诺,configureRouter() 不会触发,直到 activate() 中的承诺 return 得到解决。
我最终在 activate 中准备了如下路线:
activate(){
return this.http.fetch('url')
.then(response => response.json())
.then(docs => {
this.routerMapped = docs;
});
}
configureRouter(config, router) {
//build the routes from this.routermapped if necessary
config.map( this.routerMapped );
this.router = router;
}