Angular路由跳转时如何用Input装饰器实现父子组件传值
问题分析与解决方案
核心误区
@Input装饰器仅适用于父组件模板直接嵌套子组件的场景(即父组件HTML中显式写出<app-child>标签)。当通过路由跳转加载子组件时,子组件由Angular路由模块实例化,并非父组件直接声明,因此无法通过@Input直接传递参数。你的代码中,路由跳转后<router-outlet>中渲染的子组件实例,和父组件模板里*ngIf控制的<app-child>完全是两个独立实例,所以inputName会是undefined。
可行解决方案(满足路由跳转+值传递需求)
以下两种方案可实现路由跳转同时传递值,并将值赋值给子组件的@Input属性,达到你想要的效果:
方案1:路由查询参数传递
通过路由查询参数携带值,子组件获取后赋值给inputName:
- 修改父组件
navToChild方法
先获取输入框值,再携带查询参数跳转:
navToChild(){ // 先获取输入值,再执行路由跳转 const inputValue = this.parentData.nativeElement.value; this.router.navigate(['child'], { queryParams: { inputName: inputValue } }); }
- 修改子组件获取参数
从路由查询参数中取值并赋值给inputName:
import { Component, OnInit, Input } from '@angular/core'; import { ActivatedRoute } from '@angular/router' @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.css'] }) export class ChildComponent implements OnInit { @Input() inputName: string; constructor(private route: ActivatedRoute) { } ngOnInit() { this.route.queryParams.subscribe(params => { this.inputName = params['inputName']; console.log(this.inputName); }); } }
- 清理父组件模板
移除父组件中*ngIf控制的<app-child>标签,保留<router-outlet>即可:
<div class="container mt-5"> <div class="card"> <div class="card-header"> <h2>Main Component</h2> </div> <div class="card-body"> <input type="text" #parentData class="form-control" placeholder="enter text"/> <button class="btn btn-primary" (click)="navToChild()">submit</button> </div> </div> </div> <router-outlet></router-outlet>
方案2:共享服务传递值
通过全局共享服务存储输入值,子组件从服务中获取并赋值给inputName:
- 创建共享服务
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataShareService { private inputValueSubject = new BehaviorSubject<string>(''); inputValue$ = this.inputValueSubject.asObservable(); setInputValue(value: string) { this.inputValueSubject.next(value); } }
- 修改父组件注入服务并传值
import { Component, ViewChild, ElementRef } from '@angular/core'; import { Router } from '@angular/router'; import { DataShareService } from './data-share.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor( private router: Router, private dataShareService: DataShareService // 注入共享服务 ){} @ViewChild('parentData', {static:false}) parentData:ElementRef; navToChild(){ const inputValue = this.parentData.nativeElement.value; this.dataShareService.setInputValue(inputValue); // 存储值到服务 this.router.navigate(['child']); } }
- 修改子组件从服务取值
import { Component, OnInit, Input } from '@angular/core'; import { DataShareService } from '../data-share.service'; @Component({ selector: 'app-child', templateUrl: './child.component.html', styleUrls: ['./child.component.css'] }) export class ChildComponent implements OnInit { @Input() inputName: string; constructor(private dataShareService: DataShareService) { } ngOnInit() { this.dataShareService.inputValue$.subscribe(value => { this.inputName = value; console.log(this.inputName); }); } }
- 清理父组件模板
同方案1,移除父组件中的<app-child>标签,保留<router-outlet>。
原代码的其他问题
navToChild方法中先执行router.navigate,后续赋值parentValue和submitted的代码可能因路由跳转导致父组件状态重置而失效,正确顺序应先获取值再跳转。- 路由加载的子组件与父模板中声明的
<app-child>是独立实例,@Input绑定无法作用于路由加载的组件。
内容的提问来源于stack exchange,提问作者Shaik Subhan
相关产品推荐
相关产品推荐

