You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中使用@ViewChild访问继承类方法报错问题排查

Angular组件继承类方法调用报错问题

问题描述

在Angular应用中,通过@ViewChild访问组件继承类中的isRegistrationCompleted方法时触发报错,但将该方法直接放在ProductRegistrationComponent中时可正常运行。

报错信息

screen-product-registration.component.ts:31 ERROR TypeError: Cannot read properties of undefined (reading 'isRegistrationCompleted')

简化代码结构

screen-product-registration.component.html

<div class="row full-height">        
   <app-product-registration #productRegistration></app-product-registration>
</div>

ScreenProductRegistrationComponent

@Component({
  selector: 'app-product-registration-screen',
  templateUrl: './product-registration-screen.component.html',
  styleUrls: ['./product-registration-screen.component.css']
})
export class ProductRegistrationScreenComponent implements OnInit{ 
  
  @ViewChild(ProductRegistrationComponent) productRegistration!: ProductRegistrationComponent;
  
  ngOnInit() {
    this.startContinuousUpdate();
  }        

  startContinuousUpdate() {
    setInterval(() => {      
      const listNeedsLoading = this.productRegistration.isRegistrationCompleted(); 
      if (listNeedsLoading) {
        console.log("Entered inside IF");
      }
    }, 1000);     
  }
}

product-registration.component.ts

@Component({
  selector: 'app-product-registration',
  templateUrl: './product-registration.component.html',
  styleUrls: ['./product-registration.component.css']
})
@Injectable({
  providedIn: 'root',
})
export class ProductRegistrationComponent extends ProductService{  

}

product.service.ts

export class ProductService {
  private registrationCompleted: boolean = false;

  isRegistrationCompleted(){
    return this.registrationCompleted;
  }

  loadProducts() {   
   console.log("it works");
   this.registrationCompleted = !this.registrationCompleted;
  }
}

问题原因分析

  1. 组件初始化时机不匹配:ngOnInit执行时视图尚未完全初始化,@ViewChild获取的productRegistration实例可能还未创建完成,此时调用其方法会触发undefined错误。
  2. 组件与服务装饰器冲突:ProductRegistrationComponent同时使用@Component和@Injectable装饰器,导致Angular实例化逻辑冲突,影响组件实例的正常生成和继承关系。
  3. 不符合Angular设计规范:组件继承服务并非Angular推荐的实践,服务应通过依赖注入使用,继承方式容易引发实例化和生命周期管理问题。

解决方案

方案一:调整视图初始化时机

将startContinuousUpdate的调用移至ngAfterViewInit钩子(此时视图已初始化,@ViewChild能正确获取实例),同时增加空值检查避免意外报错:

@Component({
  selector: 'app-product-registration-screen',
  templateUrl: './product-registration.component.html',
  styleUrls: ['./product-registration.component.css']
})
export class ProductRegistrationScreenComponent implements OnInit, AfterViewInit{ 
  
  @ViewChild(ProductRegistrationComponent) productRegistration!: ProductRegistrationComponent;
  
  ngOnInit() {}        

  ngAfterViewInit() {
    this.startContinuousUpdate();
  }

  startContinuousUpdate() {
    setInterval(() => {      
      if (this.productRegistration) {
        const listNeedsLoading = this.productRegistration.isRegistrationCompleted(); 
        if (listNeedsLoading) {
          console.log("Entered inside IF");
        }
      }
    }, 1000);     
  }
}

方案二:移除组件上的@Injectable装饰器

组件无需@Injectable装饰器,移除后确保组件实例正常创建:

@Component({
  selector: 'app-product-registration',
  templateUrl: './product-registration.component.html',
  styleUrls: ['./product-registration.component.css']
})
export class ProductRegistrationComponent extends ProductService{  

}

方案三:重构为依赖注入模式(推荐)

遵循Angular最佳实践,组件通过依赖注入使用服务,而非继承:

  1. 修改ProductRegistrationComponent:
@Component({
  selector: 'app-product-registration',
  templateUrl: './product-registration.component.html',
  styleUrls: ['./product-registration.component.css']
})
export class ProductRegistrationComponent {  
  constructor(public productService: ProductService) {}

  // 封装服务方法对外暴露
  isRegistrationCompleted() {
    return this.productService.isRegistrationCompleted();
  }
}
  1. 为ProductService添加@Injectable装饰器:
@Injectable({
  providedIn: 'root',
})
export class ProductService {
  private registrationCompleted: boolean = false;

  isRegistrationCompleted(){
    return this.registrationCompleted;
  }

  loadProducts() {   
   console.log("it works");
   this.registrationCompleted = !this.registrationCompleted;
  }
}

内容的提问来源于stack exchange,提问作者JamesB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 15:32:13