在Angular2路由中使用Resolve

Kyl*_*yle 32 angular2-routing angular

在Angular 1中,我的配置如下所示:

$routeProvider
  .when("/news", {
    templateUrl: "newsView.html",
    controller: "newsController",
    resolve: {
        message: function(messageService){
            return messageService.getMessage();
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

如何在Angular2中使用resolve?

小智 28

正如alexpods已经提到的那样,似乎并没有这样的"决心".这个想法似乎是你利用了路由器提供的生命周期钩子.这些是:

  • canReuse
  • canDeactivate
  • onActivate
  • onReuse
  • onDeactivate

然后是@CanActivate.这是一个特殊的钩子,因为它是在实例化组件之前调用的.它的参数是(next, previous)您要路由到的组件以及您来自的组件(如果没有历史记录,则为null).

import {Component} from '@angular/core';
import {ROUTER_DIRECTIVES, CanActivate, OnActivate} from '@angular/router';

@Component({
    selector: 'news',
    templateUrl: 'newsView.html',
    directives: [ROUTER_DIRECTIVES]
})

@CanActivate((next) => {
    return messageService.getMessage()
        .then((message) => {
            next.params.message = message;
            return true; //truthy lets route continue, false stops routing
        });
})

export class Accounts implements OnActivate {

    accounts:Object;

    onActivate(next) {
        this.message = next.params.message;
    }
}
Run Code Online (Sandbox Code Playgroud)

我还没想到的是如何将承诺的结果输入你的onActivate - 除了将它存储在你的'下一个'组件上.这是因为onActivate也只用nextprevious调用,而不是promise的结果.我对这个解决方案不满意,但这是我能想到的最好的解决方案.

  • @shannon我在@CanActivate等装饰器中找到了DI的解决方案.使用`bootstrap`中的promise保存对appInjector的引用,并使用它来注入.看到这个plunker:http://plnkr.co/edit/SF8gsYN1SvmUbkosHjqQ?p = preview (7认同)
  • 你是如何注入你的`messageService`的?我正在尝试使用`Injector.resolveAndCreate()`.它显然无法将`bootstrap()`中指定的应用程序范围的依赖项提供给它正在创建的服务.结果是"没有Http的提供者",或者我的服务需要的其他东西. (3认同)
  • 如何在RC中完成这项工作?在RC出局后现在有更好的方法吗? (3认同)
  • 仅供参考,钩子是routerOnActivate(至少在ES6/7中) (2认同)
  • 我也有兴趣,你如何将服务依赖注入`@ CanActivate`? (2认同)

And*_*ang 28

基于@ angular/router v3-beta,这些是必需的步骤.

实现一个返回Observable或普通值的解析器:

@Injectable()
export class HeroResolver implements Resolve {

    constructor(
        private service: HeroService
    ) {}

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Hero> {
        const id = +route.params['id'];
        return Observable.fromPromise(this.service.getHero(id));
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您返回一个observable,则可以使用展开的值(第一个)route.snapshot.data.如果您希望observable本身可用,那么您需要将它包装在另一个Observable中:

return Observable.of(source$);
Run Code Online (Sandbox Code Playgroud)

将解析器添加到您的路线:

export const HeroesRoutes: RouterConfig = [
    { path: 'heroes',  component: HeroListComponent, resolve: { heroes: HeroesResolver } },
    { path: 'hero/:id', component: HeroDetailComponent, resolve: { hero: HeroResolver } }
];
Run Code Online (Sandbox Code Playgroud)

最后,提供您的解析类以及对bootstrap或主要组件的任何依赖providers:

bootstrap(AppComponent, [
    HeroesResolver, HeroService
])
Run Code Online (Sandbox Code Playgroud)

从ActivatedRoute实例获取已解析的数据:

ngOnInit() {
    this.hero = this.route.snapshot.data['hero'];
}
Run Code Online (Sandbox Code Playgroud)

请记住,快照表示组件类和解析程序类中执行状态的值.使用此方法无法使用params更新刷新数据.

Plunker:http ://plnkr.co/edit/jpntLjrNOgs6eSFp1j1P? p = preview 源材料:https://github.com/angular/angular/commit/f2f1ec0#diff-a19f4d51bb98289ab777640d9e8e5006R436


Vit*_*zeu 9

https://angular.io/docs/ts/latest/api/router/index/Resolve-interface.html"resolve "已被带回angular2路由器,但文档很稀疏.

例:

class TeamResolver implements Resolve {
  constructor(private backend: Backend) {}
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<any> {
    return this.backend.fetchTeam(this.route.params.id);
  }
}
bootstrap(AppComponent, [
  TeamResolver,
  provideRouter([{
    path: 'team/:id',
    component: TeamCmp,
    resolve: {
      team: TeamResolver
    }
  }])
);
Run Code Online (Sandbox Code Playgroud)

  • 我在`ActivatedRoute`中找到了必须注入组件的已解析值.已解析的值存储在属性中:`route.snapshot.data`.我现在也放弃了决心.在我的情况下,我期待在路由器防护的`canActivate`方法之前发生决心,但是防护总是首先被调用:( (6认同)

Ali*_*eza 5

您可以在Angular2 +中创建Resolver并将其轻松应用到路由器.看下面,这里是在Angular中创建Resolver的方法:

@Injectable()
export class AboutResolver implements Resolve<Message> {

  constructor(private aboutService: AboutService, private router: Router) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
    const id = route.params['id'];
    return this.aboutService.getById(id);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在路由器配置中:

export const Routes: RouterConfig = [
  { path: 'about',  component: AboutComponent, resolve: { data: AboutResolver } }
]; 
Run Code Online (Sandbox Code Playgroud)

最后在你的组件中:

ngOnInit() {
  this.route.data.subscribe((data: { about: About }) => {
    this.about = data.about;
  });
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*ush 4

@Andr\xc3\xa9Werlang的回答很好,但是如果你希望页面上解析的数据随着路由参数的改变而改变,你需要:

\n\n

解析器:

\n\n
@Injectable()\nexport class MessageResolver implements Resolve<Message> {\n\n  constructor(private messageService: MessageService, private router: Router) {}\n\n  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Message> {\n    const id = +route.params['id'];\n    return this.messageService.getById(id);\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

您的组件:

\n\n
ngOnInit() {\n  this.route.data.subscribe((data: { message: Message }) => {\n    this.message = data.message;\n  });\n}\n
Run Code Online (Sandbox Code Playgroud)\n