我想从一个以JSON格式获取的服务动态加载@RouteConfig的路由,
[
{ "path" : "/about" , "name" : "About" , "component" : "AboutComponent" },
{ "path" : "/contact" , "name" : "Contact" , "component" : "ContactComponent" }
]
以下是将其推入RouteDefinition数组的代码,
for (let i = 0; i < data.length; i++) {
//console.log(data[i].path+" "+data[i].name+" "+data[i].component);
this.routeConfigArray.push({ //routeConfigArray : RouteDefinition
'path': data[i].path,
'name': data[i].name,
'component': data[i].component
});
this._router.config(this.routeConfigArray); // THIS FAILS TO CONFIG PATHS ON ROUTER
}
'component':data[i].component
需要Classname,它通过String类接收它。如何将包含classname的字符串转换为类?
我也尝试使用Route类:
this.routeConfigArray.push(new Route({path: data[i].path, name: data[i].name, component:data[i].component}));
控制台错误:
路由“/ about”的组件未定义,或者不是类。 我尝试了很多方法,比如使用
eval("new "+data[i].component+"()); || new window[data[i].component] .
我对此感到困惑,并对如何解决这个问题感到困惑。
答案 0 :(得分:1)
TypeScript以某种方式编译导入到javascript中,你可以尝试这样的东西来使用eval()
(畏缩)。如果打字稿编译方式不同,这显然是行不通的,但检查一下这是否有效是很有趣的:)
for (let i = 0; i < data.length; i++) {
this.routeConfigArray.push({ //routeConfigArray : RouteDefinition
path: data[i].path,
name: data[i].name,
component: getComponent(data[i].component)
});
this._router.config(this.routeConfigArray);
}
function getComponent(comp : string) : Function {
//convert camelCase to underscore notation
let component : string = comp;
component = component[0].toLowerCase() + component.slice(1);
component = component.replace(/([A-Z])/g, function(match) {
return '_' + match.toLowerCase();
});
component += '_1';
return eval(component[comp])
}
<强>附录强>
作为使用AsyncRoute
的自己的解决方案的补充,我相信你实际上已经有了很好的解决方案。也许如果您以某种方式放置所有页面,则可以从resource
中提取path
位置,但这不是必需的。 (我的意思是从path
字符串/about
到resource
字符串./app/about/about.component
应该不会很难用一个小算法。但这可能是更新的东西。
无论如何,你可以使用AsyncRoute
警告:未经测试的代码
let routes : any[] = [
{ "path" : "/about" , "name" : "About" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" },
{ "path" : "/contact" , "name" : "Contact" , "component" : "ContactComponent", "route": "/Contact" , "resource" : "./app/contact/contact.component" }
];
routes.forEach((route : any) => {
this.routeConfigArray.push(
new AsyncRoute({
path : route.path,
loader : () => System.import(route.resource).then(m => m[route.component]),
name : route.name
})
);
});
this._router.config(this.routeConfigArray);
答案 1 :(得分:1)
你太好了@PierreDuc,我只是在看正则表达式来构建相同的功能,我想指出一些编辑将它带入工作状态....
for (let i = 0; i < data.length; i++) {
this.routeConfigArray.push({ //routeConfigArray : RouteDefinition
'path': data[i].path,
'name': data[i].name,
'component': getComponent(data[i].component).constructor
});
this._router.config(this.routeConfigArray);
}
function getComponent(comp : string) : Function {
//convert camelCase to underscore notation
let component : string = comp;
component = component[0].toLowerCase() + component.slice(1);
component = component.replace(/([A-Z])/g, function(match) {
return '_' + match.toLowerCase();
});
component += '_1.';
return eval("new "+component+comp+"()")
}
再次谢谢你老兄,它现在处于运行模式!唷!
答案 2 :(得分:1)
您可以使用@Pierre和@Pratik中的另一种方法,该方法基于返回类名称的方法:
Object.prototype.getName = function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
};
然后,您可以在组件中动态配置路由,如下所示:
ngOnInit() {
this.routes = [
{
path: '/test', component: 'OtherComponent', name: 'Test'
}
];
this.configureRoutes(this.routes);
this.router.config( this.routes);
}
configureRoutes(routes) {
var potentialComponents = [ OtherComponent ];
routes.forEach((route) => {
route.component = potentialComponents.find((component) => {
return component.name === route.component;
});
});
}
这需要提前了解可能涉及路由的潜在组件。
请参阅此plunkr for demo:https://plnkr.co/edit/KKVagp?p=preview。
看到这个问题:
答案 3 :(得分:0)
更新到上面的第一个场景: 以上动态加载UI上的路由,但为了实现这一点,我必须在我的AppComponent中提及它
import {AboutComponent} from '/path';
import {ContactComponent} from '/path';
//and then either include it in a directive or mention The component Name some place in the code
但这违背了“动态加载”的目的,因为我必须知道要求哪些组件,也不能延迟加载它们。假设我为500个组件执行此操作,我必须加载这500个组件,然后只需从上面提到的JSON中选择必须在UI上加载的组件。
解决方案(已完成并经过测试)==&gt; 我现在不必在任何指令中提及我想要加载任何导入语句的组件。 Thererby使其延迟加载和完全动态
如何强> 使用 AsyncRoute 类。
这是我的新JSON
//“route”是将它映射到[routerLink] =“['/ Home']”&amp; “resource”是组件的实际路径
[
{ "path" : "/about" , "name" : "About" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" },
{ "path" : "/contact" , "name" : "Contact" , "component" : "ContactComponent", "route": "/About" , "resource" : "./app/about/about.component" },
{ "path" : "/blog" , "name" : "Blog" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" },
{ "path" : "/news" , "name" : "News" , "component" : "AboutComponent", "route": "/About" , "resource" : "./app/about/about.component" }
]
现在到代码,我在这里获取此JSON并将其添加到routeConfigArray:RouteDefinition []并调用路由器的.config(routeConfigArray)
let routes : any[] = data; // consist the json data in array
routes.forEach((route : any) => {
this.routeConfigArray.push(
new AsyncRoute({
path : route.path,
loader : () => System.import(route.resource).then(m => m[route.component]),
name : route.name
})
);
});
this._router.config(this.routeConfigArray);
这就是它的运作方式!