在Angular 1. x中,UI路由器是我的主要工具。通过返回“解析”值的promise,路由器只需等待promise完成后再呈现指令。
或者,在Angular 1. x中,空对象不会使模板崩溃——所以如果我不介意暂时不完整的渲染,我可以在promise之后使用
填充一个最初为空的模型对象。$digest
进行渲染。然后()
在这两种方法中,如果可能的话,我更愿意等待加载视图,如果无法加载资源,则取消路线导航。这为我节省了“取消导航”的工作。编辑:请注意,这特别意味着这个问题要求一个与Angular 2期货兼容或最佳实践的方法来做到这一点,并要求尽可能避免“埃尔维斯运算符”!因此,我没有选择那个答案。
然而,这两种方法都不适用于Angular 2.0。肯定有一个标准的解决方案计划或可用。有人知道它是什么吗?
@Component() {
template: '{{cats.captchans.funniest}}'
}
export class CatsComponent {
public cats: CatsModel;
ngOnInit () {
this._http.get('/api/v1/cats').subscribe(response => cats = response.json());
}
}
以下问题可能反映了相同的问题:加载带有数据的PROMISE后的Angular 2渲染模板。请注意,问题中没有代码或公认的答案。
尝试{{model?。person.name}}
这应该等待模型不是undede
,然后渲染。
Angular 2引用这个?.
语法作为埃尔维斯运算符。在留档中引用它很难找到,所以这里是它的副本,以防他们更改/移动它:
埃尔维斯运算符 ( ?. ) 和空属性路径
Angular"埃尔维斯"运算符 ( ?. ) 是一种流畅方便的方法来防止属性路径中的null和未定义值。在这里,如果当前Hero为null,则防止视图渲染失败。
当前英雄的名字是{{当前英雄?. firstName}}
让我们详细说明这个问题和这个特定的解决方案。
当以下数据绑定标题属性为空时会发生什么?
标题是{{title}}
视图仍然呈现,但显示的值是空白的;我们只看到“标题是”,后面什么都没有。这是合理的行为。至少应用程序不会崩溃。
假设模板表达式涉及一个属性路径,如下一个示例所示,我们将在其中显示空英雄的firstName。
空英雄的名字是{{nullHero. firstName}}
JavaScript抛出空引用错误,Angular也是如此:
TypeError:无法读取[null]中null的属性'firstName'
更糟糕的是,整个视图消失了。
我们可以声称这是合理的行为,如果我们相信英雄属性永远不能为空。如果它永远不能为空,但它是空的,我们就犯了一个应该被捕获和修复的编程错误。抛出异常是正确的做法。
另一方面,属性路径中的空值有时可能没问题,尤其是当我们知道数据最终会到达时。
当我们等待数据时,视图应该毫无怨言地呈现,并且空属性路径应该像title属性一样显示为空白。
不幸的是,当当前的Hero为空时,我们的应用程序会崩溃。
我们可以用NgIF来解决这个问题
或者我们可以尝试将部分属性路径与
空英雄的名字是{{nullHero
这些方法有优点,但它们可能很麻烦,尤其是在属性路径很长的情况下。想象一下在长属性路径(例如a. b.c.d)中的某个地方防止空。
Angular"埃尔维斯"运算符 ( ?. ) 是一种更流畅、更方便的方法来防止属性路径中的空值。表达式在命中第一个空值时退出。显示是空白的,但应用程序一直在滚动,没有错误。
它也适用于长属性路径:
a?。b?。c?。d
包@角/router
具有路由的Resolve
属性。因此,您可以在呈现路由视图之前轻松解析数据。
参见:https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html
截至2017年8月28日的文档示例:
class Backend {
fetchTeam(id: string) {
return 'someTeam';
}
}
@Injectable()
class TeamResolver implements Resolve<Team> {
constructor(private backend: Backend) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<any>|Promise<any>|any {
return this.backend.fetchTeam(route.params.id);
}
}
@NgModule({
imports: [
RouterModule.forRoot([
{
path: 'team/:id',
component: TeamCmp,
resolve: {
team: TeamResolver
}
}
])
],
providers: [TeamResolver]
})
class AppModule {}
现在,在解析并返回数据之前,您的路由将不会被激活。
访问组件中已解析的数据
要在运行时从组件内访问解析的数据,有两种方法。因此,根据您的需要,您可以使用以下任一方法:
route. snapshot.para Map
返回字符串,或route. ParamMap
它返回一个可观察的对象,您可以。订阅()
。示例:
// the no-observable method
this.dataYouResolved= this.route.snapshot.paramMap.get('id');
// console.debug(this.licenseNumber);
// or the observable method
this.route.paramMap
.subscribe((params: ParamMap) => {
// console.log(params);
this.dataYouResolved= params.get('id');
return params.get('dataYouResolved');
// return null
});
console.debug(this.dataYouResolved);
我希望这能有所帮助。
编辑:棱角分明的团队已经发布了@Resolve装饰器。它仍然需要一些澄清,它是如何工作的,但是在那之前,我将在这里获取其他人的相关答案,并提供指向其他来源的链接:
编辑:此答案仅适用于Angular 2 BETA。截至本次编辑,Angular 2RC尚未发布路由器。相反,当使用Angular 2RC时,将对router
的引用替换为router-debrecated
以继续使用beta路由器。
Angular2-未来实现这一点的方法将是通过@Resolve装饰器。在那之前,最接近的传真是CanActivate
组件装饰器,根据Brandon Roberts。见https://github.com/angular/angular/issues/6611
虽然beta0不支持向组件提供解析值,但它是计划中的,这里还描述了一个解决方法:在Angular2路由中使用解析
一个beta1的例子可以在这里找到:http://run.plnkr.co/BAqA98lphi4rQZAd/#/resolved。它使用了一个非常相似的解决方法,但是稍微更准确地使用RouteData
对象而不是RouteParams
。
@CanActivate((to) => {
return new Promise((resolve) => {
to.routeData.data.user = { name: 'John' }
此外,请注意,还有一个用于访问嵌套/父路由“解析”值的示例解决方法,以及您使用1. xUI路由器时期望的其他功能。
请注意,您还需要手动注入完成此操作所需的任何服务,因为Angular Injector层次结构目前在CanActivate装饰器中不可用。简单地导入Injector将创建一个新的注入器实例,而无需从bootstrap()
访问提供程序,因此您可能需要存储引导注入器的应用程序范围副本。Brandon在此页面上的第二个Plunk链接是一个很好的起点:https://github.com/angular/angular/issues/4112