用 Angular Signal Inputs 完成一个组件的重构
昨天,园子的博客后台终于完成了前端框架升级,从 angular 15 升级到了 angular 19。Angular 从版本 17 开始了文艺复兴(renaissance)之路, 变化很大,这下可以在开发中使用 angular 的新特性了。
这篇博文记录一下昨天晚上用 angular 17 引入的新特性 signal inputs 完成了一个组件的重构。
重构前的组件模版文件
<div class="cnb-panel-header"
[class.cnb-panel-header-clickable]="headerClickable"
(click)="headerClickable ? toggleCollapsed() : undefined">
<span>{{name}}</span>
<div class="cnb-panel-header-extra" *ngIf="headerExtra">
<ng-container *ngTemplateOutlet="headerExtra; context: headerExtraContext ?? {}"></ng-container>
</div>
</div>
<div class="panel-content"
[ngClass]="collapsed ? '' : panelContentClass"
[@openClosePanel]="collapsed ? 'close' : 'open'">
<ng-content></ng-content>
</div>
重构前的组件类文件
export class CollapsePanelComponent implements OnInit {
@Input() name = '';
@Input() initCollapsed = false;
@Input() toggleIcon?: TemplateRef<any>;
@Input() headerClickable = false;
@Output() collapsedChange = new EventEmitter<boolean>(false);
@Input() headerExtra: TemplateRef<any> | null = null;
@Input() headerExtraContext?: ({ $implicit?: any } & Record<string, any>) | null;
@Input() panelContentClass: string[] = [];
collapsed = false;
constructor() { }
toggleCollapsed(collapsed?: boolean) {
const cache = this.collapsed;
this.collapsed = collapsed !== undefined ? collapsed : !this.collapsed;
if (cache !== this.collapsed) this.collapsedChange.next(this.collapsed);
}
ngOnInit() {
this.collapsed = this.initCollapsed || false;
}
}
重构后的组件模版文件,只是把 collapsed
改成了 collapsed()
重构后的组件类文件
export class CollapsePanelComponent {
@Input() name = '';
@Input() toggleIcon?: TemplateRef<any>;
@Input() headerClickable = false;
@Output() collapsedChange = new EventEmitter<boolean>(false);
@Input() headerExtra: TemplateRef<any> | null = null;
@Input() headerExtraContext?: ({ $implicit?: any } & Record<string, any>) | null;
@Input() panelContentClass: string[] = [];
collapsed = model(false);
constructor() {
effect(() => {
this.collapsedChange.next(this.collapsed());
});
}
toggleCollapsed() {
this.collapsed.update(x => !x);
}
}
这里使用 mode
没有使用 input
, 是因为组件内部需要更新 collapsed
的值,如果没有这个需要,都由父组件传值,那就用 input
。
重构中也用到了 effect
,只需要在 toggleCollapsed
方法中更新 collapsed
的值,将其他逻辑移到了 effect
的回调函数中处理。
参考: