Angular组件继承后基类组件属性未更新的调试求助
Angular组件继承后基类组件属性未更新的调试求助
问题描述
大家好,我最近在Angular里用组件继承的时候遇到了个棘手的问题:明明给子类组件传入了counter=20,但基类模板里显示的counter始终是默认值0,子类自己的counter却是正常的20。折腾半天没搞明白,来求助各位大佬!
代码展示
基类组件(BaseComponent)
import { Component, ChangeDetectorRef, OnInit, Input } from '@angular/core'; @Component({ selector: 'app-base-component', template: `<p> <b>base</b> component counter: {{ counter }} -- <b>should have been updated</b> </p> <ng-content select="[body]"></ng-content>`, styleUrls: ['base.component.css'], }) export class BaseComponent implements OnInit { @Input() public counter = 0; constructor() {} ngOnInit(): void { throw new Error('Method not implemented.'); } }
继承组件(InheritedComponent)
import { Component, OnInit } from '@angular/core'; import { BaseComponent } from '../base/base.component'; @Component({ selector: 'app-inherited-component', template: `<app-base-component> <ng-container body> <p><b>inherited</b> component counter: {{ counter }}</p> </ng-container> </app-base-component>`, styleUrls: ['inherited.component.css'], }) export class InheritedComponent extends BaseComponent { public ngOnInit(): void {} }
App组件(AppComponent)
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `<app-inherited-component [counter]="20"></app-inherited-component>`, styleUrls: ['./app.component.css'], }) export class AppComponent { name = 'everyone'; }
问题分析
其实你这里的核心问题是混淆了类继承和组件实例化的概念:
InheritedComponent确实继承了BaseComponent的类属性,所以给app-inherited-component传的counter=20会正确赋值给子类的counter(这也是子类模板里显示20的原因)。- 但子类模板里的
<app-base-component>是重新实例化了一个完全独立的BaseComponent组件,这个实例和你继承的类没有任何关联,也没收到任何counter输入,所以它的counter还是默认值0。
解决方案
既然用了类继承,就不需要在子类模板里再实例化基类组件了,直接复用继承来的属性和逻辑即可。这里有两种常见的处理方式:
方式1:直接复用基类逻辑,合并模板内容
修改InheritedComponent的模板,去掉<app-base-component>标签,直接把基类的模板内容和子类的扩展内容放在一起:
@Component({ selector: 'app-inherited-component', template: ` <p> <b>base</b> component counter: {{ counter }} -- <b>should have been updated</b> </p> <p><b>inherited</b> component counter: {{ counter }}</p> `, styleUrls: ['inherited.component.css'], }) export class InheritedComponent extends BaseComponent { public ngOnInit(): void {} }
方式2:模板复用(适合基类模板复杂的场景)
如果基类模板比较复杂,不想重复编写,可以把基类的模板抽成可复用的片段:
- 给基类模板添加模板引用:
<!-- base.component.html --> <ng-template #baseTemplate> <p> <b>base</b> component counter: {{ counter }} -- <b>should have been updated</b> </p> </ng-template> <ng-content select="[body]"></ng-content>
- 在子类中引用基类的模板:
@Component({ selector: 'app-inherited-component', template: ` <ng-container *ngTemplateOutlet="baseTemplate"></ng-container> <p><b>inherited</b> component counter: {{ counter }}</p> `, styleUrls: ['inherited.component.css'], }) export class InheritedComponent extends BaseComponent { @ViewChild('baseTemplate') baseTemplate: TemplateRef<any>; public ngOnInit(): void {} }
这样修改后,子类就会使用继承来的counter属性,基类部分的内容也会正确显示20了。
备注:内容来源于stack exchange,提问作者Mo D Genesis
相关产品推荐
相关产品推荐

