Angular routerLink激活时router-outlet内*ngIf使用及传值问题
问题原因
你的代码存在4个核心错误,导致绑定逻辑和路由导航完全不生效:
- 核心认知错误:
<router-outlet>是Angular路由的占位容器,不是普通组件宿主标签,你不能像写自定义组件标签那样,直接在<router-outlet>上写[model]输入绑定、(modelChanged)输出绑定,这些属性不会被传递到路由动态加载的组件上。 activate事件用法完全错误:activate是<router-outlet>提供的内置事件,仅在路由激活、组件实例创建完成时触发,事件返回值是当前加载的组件实例,不支持在事件绑定表达式里嵌套写模板输入输出语法,你写的(activate)='[model]="model" (modelChanged)="modelChangeHandler($event)"'属于无效模板语法,Angular无法正常解析执行。- 路由配置与模板不匹配:你给两个子路由都配置了命名出口(
rangeConge、multipleConge),但模板里只写了一个无名称的默认<router-outlet>,同时routerLink也没有指定要渲染到的命名出口,路由加载的组件找不到对应的渲染位置。 - 无效的结构指令写法:模板里写的
*ngif="routerlink"存在两个问题,一是ngIf大小写拼写错误,二是父组件类里根本没有定义routerlink变量,判断结果恒为假,<router-outlet>会被直接从DOM中移除,根本不会加载任何路由组件。
正确实现方案
方案1:保留路由加载模式,通过activate事件绑定输入输出
第一步:修正路由配置
标签页导航用默认无名出口即可,移除多余的命名出口配置:
// app-routing.module.ts { path:'congeComponent', component:CongeComponentComponent, children:[ { path:'demandeConge', component:DemandeCongeComponent }, { path:'demandeMultipleDays', component:DemandeMultipleDaysComponent } ] }
第二步:修正父组件模板
移除无效的*ngIf和错误的绑定写法,仅保留activate事件绑定:
<nav mat-tab-nav-bar dynamicHeight> <a mat-tab-link *ngFor="let tabItem of tabs" [routerLink]="tabItem.route" routerLinkActive #rla="routerLinkActive" [active]="rla.isActive"> {{tabItem.label}} </a> </nav> <router-outlet (activate)="onRouteActivate($event)"></router-outlet>
第三步:在父组件类中手动处理组件实例绑定
拿到路由加载的组件实例后,手动给输入属性赋值、订阅输出事件:
// 父组件ts文件 onRouteActivate(componentRef: any) { // 匹配当前激活的多日申请组件 if(componentRef instanceof DemandeMultipleDaysComponent) { // 手动传递输入属性 componentRef.model = this.model; // 手动订阅输出事件 componentRef.modelChanged.subscribe((newModel: Date[]) => { this.modelChangeHandler(newModel); }) } // 其他路由组件的输入输出绑定可在此处扩展判断 }
如果需要保留标签切换时的组件状态,可以配合RouteReuseStrategy做路由复用,避免组件重复销毁重建。
方案2:非路由加载模式(更简单的标签实现)
如果不需要URL同步标签状态、不需要支持链接直达指定标签,可以放弃路由加载子组件,直接通过routerLinkActive的激活状态控制组件显示,原生输入输出绑定可以直接生效:
<nav mat-tab-nav-bar dynamicHeight> <a mat-tab-link routerLink="demandeConge" routerLinkActive #rlaRange="routerLinkActive" [active]="rlaRange.isActive" [routerLinkActiveOptions]="{exact: true}"> Range of days </a> <a mat-tab-link routerLink="demandeMultipleDays" routerLinkActive #rlaMultiple="routerLinkActive" [active]="rlaMultiple.isActive" [routerLinkActiveOptions]="{exact: true}"> Multiple days </a> </nav> <app-demande-conge *ngIf="rlaRange.isActive"></app-demande-conge> <app-demandeMultipleDays *ngIf="rlaMultiple.isActive" [model]="model" (modelChanged)="modelChangeHandler($event)"></app-demandeMultipleDays>
这种写法不需要手动处理路由实例绑定,逻辑更直观,缺点是组件切换时默认会销毁重建,URL不会同步当前选中的标签状态。
内容的提问来源于stack exchange,提问作者Mouad
相关产品推荐
相关产品推荐

