首先,我们需要问自己为什么要创建一个新的按钮组件类型,当我们已经有本地的按钮组件了。可能是像这样:
- 利用一些 Angular 助手,如动画
- 在执行某个点击处理程序期间禁用按钮。
- 进度指示。
- ...
如果可以使用本机按钮(解决方案 0)解决要求,请坚持使用。否则,继续进行。
在创建可重复使用的按钮组件之前,我们需要知道两件重要的事情:
K1 只有少量 HTML 元素可以被禁用,这意味着即使元素被禁用,点击处理程序也会触发。https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements
K2 在 Angular 中,外部事件无法从内部进行控制。https://github.com/angular/angular/issues/12630
解决方案 1. 将点击处理程序作为输入
要解决K2的问题,您可以使用@Input
回调而不是事件绑定。然后您就可以从内部控制它,
甚至可以在内部访问回调结果。代码示例如下:
<my-button [myClick]="doIt"> or with arguments <my-button [myClick]="doIt.bind(1)">
@HostListener('click') onClick(event) {
this.myClick();
}
由于您完全控制回调,因此当其处于disabled
状态时,您可以省略调用它。
需要这种解决方案的问题是带有进度指示的按钮。当您完全控制回调时,库按钮可以启动/停止进度条的动画,甚至在进行中时通过禁用它来阻止其他点击。与此模块中的进度按钮相比https://github.com/michaeldoye/mat-progress-buttons,您需要为每个按钮实例启动/停止动画!
缺点:外观不标准。您的库用户会问为什么回调是输入而不是事件绑定...
解决方案2. CSS
您可以尝试使用CSS pointer-events:none
解决K1。它将在表面上起作用,阻止用户鼠标触发的点击事件。但是,您仍然可以在按钮上进行编程点击。myButton.click()
仍然会在按钮处于“禁用”状态时触发。
缺点:'禁用'元素仍然可以点击
。可能不适合您的库用户编写自动化测试。
解决方案3. 组件化本地按钮
为了使禁用和事件按预期工作,您需要直接在HTML按钮元素上应用组件。在Angular Material中,它看起来像<button mat-button>
,
https://github.com/angular/components/blob/master/src/material/button/button.ts#L66
而且非常简单:
@Component({
selector: 'button[my-button]',
template: '<ng-content></ng-content>'
})
并且使用它:
<button my-button (click)="doIt()" [disabled]="isDisabled">Save</button>
现在当my-button
被禁用时,点击事件不会触发。
缺点:必须有原生按钮,并且my-button
看起来更像指令而不是组件。
结论
我建议选择最符合要求的解决方案,而不是CSS hack。
pointer-events: none
将禁用其他鼠标事件。因此,像工具提示这样的东西将不再起作用,因为没有鼠标事件被触发。 - Jacob Roberts