【问题标题】:Angular2 using @Inputs with <router-outlet>sAngular2 使用 @Inputs 和 <router-outlet>s
【发布时间】:2016-03-25 15:29:07
【问题描述】:

我的页面中有一个子导航,它在公共主视图下方显示一些子视图。我想通过&lt;router-outlet&gt; 将一个对象传递给子视图,以便我可以在主组件中检索一次数据并与我的子组件共享。

注意:如果我在 main.html 中包含指令 &lt;one&gt;&lt;/one&gt;,它会起作用,但这不是我想要的行为。

主视图:

<h1>Details</h1>   
<a [router-link]="['./sub1']">One</a> | 
<a [router-link]="['./sub2']">Two</a> | 
<a [router-link]="['./sub3']">Three</a>   
<hr/>  
<router-outlet [data]="maindata"></router-outlet>

子视图 1:

<h2>{{ data.name }}</h2>
...

主视图:

@Component({
    selector: 'main-detail',
    directives: [ROUTER_DIRECTIVES],
    templateUrl: './main.html'
})
@RouteConfig([
    { path: '/', redirectTo: '/one' },
    { path: '/one', as: 'One', component: OneComponent },
    { path: '/two', as: 'Two', component: TwoComponent },
    { path: '/three', as: 'Three', component: ThreeComponent }
])
export class MainComponent {
    maindata: Object = {name:'jim'};
}

子视图 1:

@Component({
    selector: 'one',
    directives: [CORE_DIRECTIVES],
    inputs: ['data'],
    templateUrl: './one.html'
})
export class OneComponent {
    @Input() data;
}

【问题讨论】:

标签: typescript angular angular2-template


【解决方案1】:

如果是简单数据,你可以通过RouteParams传递它们

<a [router-link]="['./sub3'],{name:'jim'}">Three</a>

然后在您的子视图中

@Component({
    selector: 'one',
    directives: [CORE_DIRECTIVES],
    templateUrl: './one.html'
})
export class OneComponent {
    data: any;
  constructor(params: RouteParams){
    this.data = params.get('data');
  }
}

您还可以通过将RouterConfig 移动到组件内部来设置路由以始终从组件传递参数(注意,这不是通常的做法)

export class AppCmp {
  history: string[] = [];
  constructor(public list: PersonalizationList,
              private router_: Router) {
    list.get('histoy', (response) => {
      this.history = response;
    });
    router_.config([
      { path: '/', component: HomeCmp, as: 'Home', data: this.history },
      { path: '/about', component: AboutCmp, as: 'About' }
    ]);
  }
}

Credit to the Source

如果您打算做一些更复杂的事情,我建议使用服务在路由/组件之间进行通信。这实际上是我更喜欢这样做的方式。

示例服务:

import {Injectable} from 'angular2/angular2';

@Injectable()
export class CarsService {
  list1: array<any> = ['a','b','c','d'];
  list2: array<any>;

  constructor() {
    this.list2 = [1,2,3,9,11];
  }
}

如何注入服务:

export class Cars {
  constructor(cars:CarsService) {
    this.cmpList1 = cars.list1;
    this.cmpList2 = cars.list2;
  }
}

通过这种方式,您可以使用该服务进行通信,而不受父/子或其他奇怪限制的影响。

【讨论】:

  • 不幸的是,我需要传递的不仅仅是简单的数据(一个对象)。我试图避免创建一个仅负责在两个组件之间传递数据的服务,但似乎我别无选择。
  • 使用 Angular 2.0.0-beta.8 Injectable 可以从 'angular2/core' 导入
  • 不幸的是,新的 v3 路由器已经过时了。
  • 是的,不幸的是,当我有最多时间在 S.O.代码仍然每天都在变化,我决定我不能通过并不断更新答案,因为许多问题也已经过时了。新路由器的方法虽然类似,但我仍然建议使用服务。
  • 有一个关于这个主题的github问题讨论。至于 Anuglar rc-0.5,他们决定不允许 @Input like param 传递 并且有一个关于使用服务来完成这项工作的教程Parent and children communicate via a service
【解决方案2】:

看起来语法已更改。下面对我有用~Angular4.0.0

HTML(传递路由参数)

<li><a [routerLink]="['/templatecreate',{mode:'New'}]">New Job</a></li>

组件

constructor(private route: ActivatedRoute) { }

ngOnInit() {       
  this.getTemplate();

  this.sub = this.route.params.subscribe(params => { this.id = params['mode'];
  console.log("Routing Mode", this.id);    
  });
}

【讨论】:

    【解决方案3】:

    我认为传递数据的正确 Angular2 方式是通过依赖注入(通过使用服务),否则用户将能够看到您在浏览器的 URL 中传递的数据。

    此外,使用服务将允许“关注点分离”,这意味着组件 A 不应依赖于组件 B。

    依赖注入链接:

    1) https://angular.io/guide/dependency-injection

    2) https://angular.io/guide/dependency-injection-in-action

    3)https://www.youtube.com/watch?v=MJrw43GP2u0

    【讨论】:

    • 组件应该采用@inputs,而不是将它们与服务密不可分。我不想为了使用您的组件而创建服务。我们需要一种在路由时将输入传递给组件的方法。
    • @RickO'Shea 2019 尚未改进,仍然没有输入 我是 Angular 新手 我尝试使用路由时的第一个想法是使用输入,真可惜
    【解决方案4】:

    我们有一个很大的 Angular 项目(刚从 Angular 开始,所以解决方案和我们的理解一样好 :-))。

    shell 组件可以调用 4 个(基于路由的)“动作”模块中的任何一个 - 每个模块都有自己的服务(但没有组件视图),并且可以调用 6 个(基于路由的)共享组件中的任何一个。共享组件在所有 4 个服务之间共享,因此它们不能有任何特定于调用模块的逻辑。

    我们正在使用一个服务解析器 ActionModuleServiceResolver,它 DI 是所有 4 个操作服务。根据状态(RouterStateSnapshot)URL,我们返回相应的服务。

    @Injectable()
    export class ActionModuleServiceResolver implements Resolve<ActionModuleService> {
    
      constructor(private _mod1: ModOneService,
        private _mod2: ModTwoService, private _mod3: ModThreeService,private _mod4: ModFourService) { }
    
      resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): ActionModuleService {
        if(state.url.includes(`/${ActionModuleType.ModOne}/`))
          return this._mod1;
        else if(state.url.includes(`/${ActionModuleType.ModTwo}/`))
          return this._mod2;
    ....
    else
      return null;
      }
    }
    

    每个动作模块的路由模块路由到共享组件,如下所示:

        const routes: Routes = [
      {
        path: 'sharedMod1', component: SharedModOneComponent, data: {
          title: `ModOne_SharedModOne`,
          routeName: 'sharedMod1'
        }, resolve: { actionModule: ActionModuleServiceResolver }
      },
    

    接下来,每个SharedModule通过DI获取激活路由,获取调用服务:

    //SharedModOne.component.ts
    constructor(protected route: ActivatedRoute) {}
    
      ngOnInit() {
        this.actionModSvc= this.route.snapshot.data['actionModule'];
        this.actionModSvc.getDesignFile(this.route);
      }
    

    希望这对某人有所帮助,如果可以改进,请告诉我。

    谢谢,

    RDV

    【讨论】:

      猜你喜欢
      • 2020-01-19
      • 1970-01-01
      • 2017-10-05
      • 1970-01-01
      • 1970-01-01
      • 2017-12-29
      • 2020-11-23
      • 1970-01-01
      • 2017-02-06
      相关资源
      最近更新 更多