当前位置:  开发笔记 > 编程语言 > 正文

等待Angular 2在渲染视图/模板之前加载/解析模型

如何解决《等待Angular2在渲染视图/模板之前加载/解析模型》经验,为你挑选了3个好方法。

在Angular 1.x中,UI-Router是我的主要工具.通过返回"解析"值的承诺,路由器将在呈现指令之前等待承诺完成.

或者,在Angular 1.x中,null对象不会使模板崩溃 - 所以如果我不介意暂时不完整的渲染,我可以$digestpromise.then()填充最初为空的模型对象后使用它进行渲染.

在这两种方法中,如果可能的话,我宁愿等待加载视图,如果无法加载资源,则取消路由导航.这为我节省了"取消导航"的工作.编辑:注意这具体意味着这个问题要求Angular 2期货兼容或最佳实践方法来执行此操作,并要求尽可能避免使用"Elvis操作符"!因此,我没有选择那个答案.

但是,这两种方法都不适用于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渲染模板.请注意,问题中没有代码或接受的答案.



1> tehaaron..:

试试{{model?.person.name}}这个应该等待模型不是undefined然后渲染.

Angular 2将此?.语法称为Elvis运算符.在文档中引用它很难找到,所以这里是它的副本,以防它们更改/移动它:

Elvis运算符(?.)和null属性路径

Angular"Elvis"运算符(?.)是一种流畅且方便的方法,可以防止属性路径中的null和undefined值.如果currentHero为null,则保护视图呈现失败.

The current hero's name is {{currentHero?.firstName}}

让我们详细说明问题和这个特定的解决方案.

当以下数据绑定title属性为null时会发生什么?

The title is {{ title }}

视图仍然呈现但显示的值为空白; 我们只看到"标题是",之后什么都没有.这是合理的行为.至少应用程序不会崩溃.

假设模板表达式涉及属性路径,如下一个示例所示,其中我们显示空英雄的firstName.

The null hero's name is {{nullHero.firstName}}

JavaScript抛出空引用错误,Angular也是如此:

TypeError: Cannot read property 'firstName' of null in [null]

更糟糕的是,整个观点都消失了.

如果我们认为英雄财产绝不能为空,我们可以声称这是合理的行为.如果它必须永远不是null而且它是null,那么我们已经编写了一个应该被捕获并修复的编程错误.抛出异常是正确的做法.

另一方面,属性路径中的空值可能不时,特别是当我们知道数据最终到达时.

在我们等待数据的同时,视图应该在没有投诉的情况下呈现,并且null属性路径应该像title属性一样显示为空白.

不幸的是,当currentHero为null时,我们的应用程序崩溃了.

我们可以用NgIf来解决这个问题

The null hero's name is {{nullHero.firstName}}

或者我们可以尝试使用&&链接属性路径的一部分,因为知道表达式在遇到第一个null时会失效.

The null hero's name is {{nullHero && nullHero.firstName}}

这些方法具有优点,但它们可能很麻烦,尤其是在属性路径很长的情况下.想象一下,在诸如abcd之类的长属性路径中的某处保护null

Angular"Elvis"运算符(?.)是一种更流畅,更方便的方法来防范属性路径中的空值.当它达到第一个空值时,表达式会失效.显示为空白但应用程序不断滚动且没有错误.

The null hero's name is {{nullHero?.firstName}}

它也适用于长属性路径:

a?.b?.c?.d


@shannon我不相信是这样的.请参阅我的更新答案和ng2文档.
此运算符现在称为["安全导航运算符"](https://angular.io/docs/ts/latest/guide/template-syntax.html#!#safe-navigation-operator).

2> TetraDev..:

该套餐@angular/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 {
  constructor(private backend: Backend) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable|Promise|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.paramMap 返回一个字符串,或者

    route.paramMap它会返回一个Observable .subscribe().

例:

  // 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);

我希望有所帮助.


看起来你可以从快照http://stackoverflow.com/a/38313301/1138984获取它

3> shannon..:

编辑:角度团队已经发布了@Resolve装饰器.它仍然需要一些澄清,如何工作,但在此之前,我将在这里采取其他人的相关答案,并提供其他来源的链接:

StackOverflow:在Angular2路由中使用Resolve

StackOverflow:GünterZöchbauer的使用示例

解决文档

GitHub上的路由器补丁

RC4 ChangeLog

RC4发布推文


编辑:此答案仅适用于Angular 2 BETA.在此编辑中,未针对Angular 2 RC发布路由器.相反,当使用Angular 2 RC时,请替换为routerwith的引用router-deprecated以继续使用beta路由器.

Angular2-未来的实现方式将通过@Resolve装饰器实现.在那之前,最接近的传真是CanActivate组件装饰,每个Brandon Roberts.请参阅https://github.com/angular/angular/issues/6611

尽管beta 0不支持向Component提供已解析的值,但它是计划好的,此处还介绍了一种解决方法:在Angular2路由中使用Resolve

可在此处找到beta 1示例:http://run.plnkr.co/BAqA98lphi4rQZAd/#/resolved.它使用非常类似的解决方法,但稍微更准确地使用RouteData对象而不是RouteParams.

@CanActivate((to) => {
    return new Promise((resolve) => {
        to.routeData.data.user = { name: 'John' }

另请注意,也有用于访问嵌套/父路由为例变通方法"解决"的价值观,以及和其他的功能,你期望,如果你已经使用1.x的UI的路由器.

请注意,您还需要手动注入完成此操作所需的任何服务,因为CanActivate装饰器中当前不提供Angular Injector层次结构.简单地导入一个喷油器会创建一个新的喷油器的实例,而无需访问来自供应商bootstrap(),所以你可能要存储自举喷射器的应用范围内的副本.布兰登在这个页面上的第二个Plunk链接是一个很好的起点:https://github.com/angular/angular/issues/4112

推荐阅读
coco2冰冰
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有