首页 > 解决方案 > 如何实现嵌套二级路由并仍然从孩子那里获取数据?角 6

问题描述

我的目标是将数据从路由子级发送到父级。我想从子级获取变量的引用,该引用通过辅助路由嵌套在子级到父级,以便将变量同步到父级。这个变量最终将是表单验证状态的布尔值。不幸的是,当我使用 Behavior Subject 时,我认为我必须使用组件选择器,它似乎不能很好地与我的应用程序中的路由配合使用。

这是应用程序模板中的一个示例......似乎当我添加 app-new-user 组件选择器时,它搞砸了名为 router outlet 的 newuserinput :(

<!-- To BLADE LAYER 3 -->
<router-outlet></router-outlet>
<!-- <router-outlet name="newuserinput" (newUserInfoCompleteEvent)="receiveNewUserInfoComplete($event)"></router-outlet> -->
<router-outlet (activate)='getVState($event); ' name="newuserinput"></router-outlet>
<router-outlet name="newuserorginfo"></router-outlet>
<router-outlet name="newusersupervisorinfo"></router-outlet>
<router-outlet name="newusersecurityinfo"></router-outlet>
<!-- end -->



<!-- For ViewChild: bringing form validity state from child -->
<!-- <app-new-user-input style="display:none;"></app-new-user-input> -->
<!-- can't do this because putting the child component selector in the parent disables the childs router outlet -->

在我准备的stackblitz 原型中,子/父结构成功地与服务一起工作以显示所需的信息;但是,只要我用命名路由替换父(应用程序组件)中的组件选择器(就像我上面提供的应用程序的片段中一样),就会中断。我对这个原型的目标是在父节点上显示“来自次要孩子的你好”,并在地址栏中正确显示次要路由参数,如下所示: https://behavior-subject-0007.stackblitz.io/(child: child/(secondarychild:secondarychild))

我的问题:那么,我如何实现嵌套二级路由并仍然通过从子级到父级的引用获取数据,以便地址栏显示如下https://behavior-subject-0007.stackblitz.io/(child:child/ (secondarychild:secondarychild)) ?

我可以为此使用行为主题还是有更好的方法?我正在考虑尝试实施AJ2_82 的解决方案

我还通过使用组件主机元数据来研究路由子组件上的简单属性绑定......

我对编程比较陌生,所以可能有一个“明显”的解决方案,感谢您提供的任何帮助。

如果您分享满足相同要求的方式(通过从孩子到父母的引用命名路由器出口地址和数据),我会全力以赴。谢谢你。

标签: angularangular-ui-routerrxjsbehaviorsubject

解决方案


解决问题的方法之一是使用事件,将事件发射器加载到您的共享服务public onChange: EventEmitter<string> = new EventEmitter<string>();,然后将其从父级广播到其子级,或者相反,像这样

changeMessage(message: string) {
    this.currentMessage = of(message)
    this.onChange.emit(message); 
  }

在每次出现您希望它加入通信配置单元的所需组件时,从该服务添加一个事件捕获器:this.myService.onChange.subscribe(message=> this.message = message);

通过这种方式,您可以实现一种“向外”但功能完整的方法,以便在路线之间实时共享数据。

看到这个样本。或者您可以看到这个稍微不同的实现,它合并了同级组件和路由。


或者你可以使用特殊的路由参数

通过这种方式,您不会允许来自另一个共存层次结构的任何外部组件干扰在定义的路由模块之间交换的这些内部消息,因为您在它们之间不经意地传递它们。

您可以这样配置模块:

export const routes: Routes = [
  { path: '', redirectTo: 'component-one/:message', pathMatch: 'full' },
  { path: 'component-one/:message', component: ComponentOne },
  { path: 'component-two/:message', component: ComponentTwo,
    children: [
      { path: '', redirectTo: 'child-one', pathMatch: 'full' },
      { path: 'child-one/:message', component: ChildOne },
      { path: 'child-two/:message', component: ChildTwo }
    ]
  }
];

因此,对这些子关系之一的每次调用都伴随着一些参数,这些参数将在其中的组件 html 核心中使用。

在下面的示例中,我将函数调用中的参数设为可选,以判断它是否由组件加载触发,因此重新生成,尽管它源自按钮单击,因此只是分别更新为一些自定义部分。

newMessage(param?) {

    if(typeof(param) === 'undefined')
       this.message = "Parent";
    else
       this.message = param;

    var actualroute=this.router.routerState.snapshot._root.children[0].children[0].value.url[0].path;
    this.router.navigate(['/component-two', this.message , actualroute, this.message  ],{relativeTo: this.route});   
}

您可以在这里看到这一切。感谢这个有趣的挑战。

弱点:每次更新变量message时,路由器都会重新导航到相同的层次结构,这会花费时间,尤其是对于更大的实现。

强项:当您调用 arouter.navigate时,可以在组件之间传递自定义数据,例如 'mesage1' 用于子级,'message2' 用于父级:this.router.navigate(['/component-two', 'message2' , 'child-one', 'message1']);。这可以使用服务来完成,但非常复杂且条件复杂。


推荐阅读