Angular子组件获取父组件传值失败且路由跳转异常问题咨询
Angular父子组件通信及路由异常问题解决
问题根因分析
核心错误点
- 事件绑定大小写不匹配:Child1声明的
@Output()事件名为getData,父组件模板中绑定的是(getdata),Angular事件绑定区分大小写,导致父组件接收不到Child1抛出的事件,clickedData永远为初始空值 - Input绑定实例不匹配:你在父组件代码中调用了
this.router.navigate(['child2']),说明是通过路由加载Child2页面,而父组件模板中写的<app-child2 [clickedItem] = "clickedData">是给嵌入在父模板中的Child2实例传值,和路由生成的Child2实例毫无关系,自然拿不到值 - 自动跳登录页问题:大概率是路由配置问题,要么Child2路由配置了登录校验守卫,当前无有效登录态;要么路由配置顺序错误,通配符路由
**(指向登录页)优先级高于Child2路由,导致匹配异常 - 生命周期取值时机错误:
ngOnInit仅在组件初始化时执行一次,若你是先初始化Child2再点击Child1传值,此时ngOnInit已经执行完毕,自然拿不到后续更新的Input值
对应解决方案
场景1:Child2是父组件内嵌入式子组件,不需要路由跳转
直接删掉父组件里的路由跳转代码,同时修正事件绑定和取值逻辑:
- 修正父组件事件绑定
<!-- 父组件模板 --> <app-child1 (getData)="getDataEvent($event)" ></app-child1> <app-child2 [clickedItem] = "clickedData" ></app-child2>
- 删掉父组件事件处理中的路由跳转逻辑
// 父组件ts clickedData:any; getDataEvent($event: any) { this.clickedData = $event; // 删掉 this.router.navigate(['child2']) 这行 }
- 修正Child2的取值逻辑,监听Input变化:
// Child2 ts 写法1:用ngOnChanges监听 import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; @Input() clickedItem: any = ''; ngOnChanges(changes: SimpleChanges) { if(changes['clickedItem'] && changes['clickedItem'].currentValue) { alert(this.clickedItem) } } // 写法2:用setter监听 private _clickedItem: any = ''; @Input() set clickedItem(val: any) { this._clickedItem = val; alert(this._clickedItem) } get clickedItem() { return this._clickedItem; }
场景2:确实需要路由跳转到独立的Child2页面
此时不能用@Input传值,要通过路由参数或者公共服务传值:
方案A:通过路由query参数传值(适合简单数据)
// 父组件ts getDataEvent($event: any) { this.router.navigate(['child2'], { queryParams: { clickedItem: JSON.stringify($event) // 复杂数据转json字符串 } }) } // Child2 ts import { ActivatedRoute } from '@angular/router'; constructor(private route: ActivatedRoute) {} ngOnInit() { const item = this.route.snapshot.queryParams['clickedItem']; this.clickedItem = item ? JSON.parse(item) : ''; alert(this.clickedItem) }
方案B:通过公共服务传值(适合复杂、大量数据)
- 新建公共服务
ng generate service data/data-share
- 服务代码
// data-share.service.ts import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataShareService { private clickedItemSubject = new BehaviorSubject<any>(null); clickedItem$ = this.clickedItemSubject.asObservable(); setClickedItem(data: any) { this.clickedItemSubject.next(data); } }
- 父组件传值
// 父组件ts constructor(private dataShareService: DataShareService) {} getDataEvent($event: any) { this.dataShareService.setClickedItem($event); this.router.navigate(['child2']) }
- Child2取值
// Child2 ts constructor(private dataShareService: DataShareService) {} ngOnInit() { this.dataShareService.clickedItem$.subscribe(data => { if(data) { this.clickedItem = data; alert(this.clickedItem) } }) }
路由自动跳登录页修复
- 先调整路由配置顺序:把Child2的路由配置放在通配符
**路由前面,Angular路由匹配是从上到下优先匹配 - 检查Child2路由的
canActivate/canMatch守卫配置,确认当前登录态满足守卫校验条件
内容的提问来源于stack exchange,提问作者mevr
相关产品推荐
相关产品推荐

