通过使用测试主机组件(which is my and Angular's suggested strategy),您可以实现这一点;即使使用OnPush.我已经对你的init方法可能做什么自由—长话短说,你需要设置你的标题两次,因为这是你如何写你的更改.
html用于简单组件
<div id="initStatus">initialized: {{initialized}}</div>
TS文件文件
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'my-child-component',
templateUrl: './simple.component.html',
styleUrl: './simple.component.css'
})
export class SimpleComponent implements OnChanges {
initialized = false;
@Input({ required: true }) input_title: String = '';
ngOnChanges(changes: SimpleChanges): void {
const simpleChange = changes['input_title'];
if (simpleChange.previousValue && (simpleChange.currentValue !== simpleChange.previousValue)) {
this.init(); // I WANT to test this method
}
}
private init(): void {
this.initialized = true;
}
}
等级库文件
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SimpleComponent } from './simple.component';
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';
@Component(({
template: `<my-child-component [input_title]="title"></my-child-component>`,
}))
class TestHostComponent {
title = 'first title';
}
describe('SimpleComponent', () => {
let component: TestHostComponent;
let fixture: ComponentFixture<TestHostComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [SimpleComponent, TestHostComponent]
})
.compileComponents();
fixture = TestBed.createComponent(TestHostComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should init', () => {
const debugElement = fixture.debugElement.query(By.css('#initStatus'));
expect(debugElement.nativeElement.textContent).toBe('initialized: false');
component.title = 'second title'; // here is what you are missing
fixture.detectChanges();
expect(debugElement.nativeElement.textContent).toBe('initialized: true');
});
});
Now, let's discuss ngOnChanges. It runs for EVERY CHANGE, which is why I avoid it entirely to help prevent performance issues.
Here is the new TS文件文件 that does the same thing but with a setter and OnPush
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
@Component({
selector: 'my-child-component',
templateUrl: './simple.component.html',
styleUrl: './simple.component.css',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SimpleComponent {
currentTitle: string
initialized = false;
@Input({ required: true }) set input_title(value: string) {
const changed = !!this.currentTitle;
this.currentTitle = value;
if (changed) {
this.init();
}
}
private init(): void {
this.initialized = true;
}
}
以这种方式写出来会让你更清楚地看到,你的init只有在你改变一个现有的标题时才会被调用.
祝你好运,编程快乐!