我正在重写我的应用程序以使用 TailwindCSS,这促使我制作小组件,以避免必须在每个按钮或链接上放置相同的 CSS 类列表。
这让我遇到了这个问题,在我将 setter 或 OnChanges 逻辑推入一个输入为 static 且 will not change 的组件之前,我试图推理出这个问题,因为我目前不明白为什么它会使用默认值进行渲染而不是硬编码到其定义中的输入值。
我想让这些 Tailwind 组件尽可能轻,所以我想避免在不需要时添加逻辑。因此,我想对此做出解释:
成分:
import {Component, Input} from '@angular/core';
import {NgClass} from '@angular/common';
import {RouterLink} from '@angular/router';
@Component({
selector: 'tw-link',
templateUrl: 'tw-link.component.html',
styleUrls: ['tw-link.component.scss'],
standalone: true,
imports: [
NgClass,
RouterLink
]
})
export class TwLinkComponent {
@Input({ required: true }) public linkName: string;
@Input({ required: true }) public linkHref: string;
@Input() public linkType: string;
@Input() public linkExternal: boolean = false;
@Input() public linkStyle: string = "default";
@Input() public linkDisabled: boolean = false;
@Input() public buttonOutline: boolean = false;
}
<a
[routerLink]="linkExternal ? null : linkHref"
[attr.href]="linkExternal ? linkHref : null"
[attr.type]="linkType ? linkType : null"
[ngClass]="{
'tw-link-base': true,
'tw-link-default': linkStyle === 'default',
'tw-link-primary': linkStyle === 'primary',
'tw-link-danger': linkStyle === 'danger',
'tw-link-warning': linkStyle === 'warning',
'tw-link-info': linkStyle === 'info',
}"
>
{{ linkName }}
</a>
使用静态输入值对子组件进行父组件实例化:
Working component:
<tw-link linkName="About" linkHref="about"></tw-link>
Not working component:
<tw-link linkName="Chris Routh" linkHref="https://routh.io" [linkExternal]="true"></tw-link>
使用内部链接的第一次调用完美呈现,所有预期的输入值都被正确解析和呈现。
第二个带有外部链接的调用是失败的地方。
[routerLink]="linkExternal ? null : linkHref"
检查按预期工作,并且routerLink没有添加到锚标记,但是[attr.href]="linkExternal ? linkHref : null"
似乎只查看默认值,并且从不渲染href
属性。
为什么组件第二次使用就不行了?我对
Input()
和生命周期的理解显然存在漏洞,因为如果这些输入值是 非静态,我只希望需要一个设置器。
FWIW 我还有一个非常相似的按钮组件,我将在此处添加它作为示例,它也按预期工作并每次都使用静态输入进行渲染:
import {Component, Input} from '@angular/core';
import {NgClass} from '@angular/common';
@Component({
selector: 'tw-button',
templateUrl: 'tw-button.component.html',
styleUrls: ['tw-button.component.scss'],
standalone: true,
imports: [
NgClass
]
})
export class TwButtonComponent {
@Input({ required: true }) public buttonName: string;
@Input() public buttonType: string = "button";
@Input() public buttonShape: string = "square";
@Input() public buttonStyle: string = "default";
@Input() public buttonOutline: boolean = false;
@Input() public buttonDisabled: boolean = false;
}
<button
type="{{ buttonType }}"
[disabled]="buttonDisabled"
[class.tw-button-disabled]="buttonDisabled"
[ngClass]="{
'tw-button-base': true,
'tw-button-default' : buttonStyle === 'default',
'tw-button-primary' : buttonStyle === 'primary',
'tw-button-danger' : buttonStyle === 'danger',
'tw-button-warning' : buttonStyle === 'warning',
'tw-button-info' : buttonStyle === 'info',
'tw-button-outline' : buttonOutline,
'tw-button-square': buttonShape === 'square',
'tw-button-circle': buttonShape === 'circle',
}"
>
{{ buttonName }}
</button>
``
无论传入的值如何,
[routerLink]
指令都会应用于锚元素。由于null
作为值传入,因此该指令会在 href 属性上设置 null
值,从而清除您已经设置的 href明确设置。
指令不能有条件地应用,但是存在一种解决方法,即将组件拆分为两个模板并使用 ngTemplateOutlet
指令在它们之间切换。 (基于https://stackoverflow.com/a/36754176/19748698) 示例:
<ng-container [ngTemplateOutlet]="linkExternal ? externalTemplate : internalTemplate">
<ng-template #internalTemplate>
<a [routerLink]="linkHref [attr.type]="linkType ? linkType : null" [ngClass]="{
'tw-link-base': true,
'tw-link-default': linkStyle === 'default',
'tw-link-primary': linkStyle === 'primary',
'tw-link-danger': linkStyle === 'danger',
'tw-link-warning': linkStyle === 'warning',
'tw-link-info': linkStyle === 'info',
}">{{ linkName }}
</a>
</ng-template>
<ng-template #externalTemplate>
<a [attr.href]="linkHref" [attr.type]="linkType ? linkType : null" [ngClass]="{
'tw-link-base': true,
'tw-link-default': linkStyle === 'default',
'tw-link-primary': linkStyle === 'primary',
'tw-link-danger': linkStyle === 'danger',
'tw-link-warning': linkStyle === 'warning',
'tw-link-info': linkStyle === 'info',
}">
{{ linkName }}
</a>
</ng-template>
</ng-container>
Tailwind 类可以放入单独的变量中以避免代码重复。