AngularJS有&参数,你可以把一个回调传递给一个指令(例如AngularJS的回调方式)。是否可以将回调函数作为@Input传递给Angular组件(如下所示)?如果不是,那最接近AngularJS的功能是什么?
@Component({
selector: 'suggestion-menu',
providers: [SuggestService],
template: `
<div (mousedown)="suggestionWasClicked(suggestion)">
</div>`,
changeDetection: ChangeDetectionStrategy.Default
})
export class SuggestionMenuComponent {
@Input() callback: Function;
suggestionWasClicked(clickedEntry: SomeModel): void {
this.callback(clickedEntry, this.query);
}
}
<suggestion-menu callback="insertSuggestion">
</suggestion-menu>
更新
这个答案是在Angular 2还处于alpha阶段的时候提交的,当时很多特性都无法使用/没有文档记录。虽然下面的方法仍然有效,但这种方法现在已经完全过时了。我强烈推荐下面接受的答案。
原来的答案
是的,事实上它是,但是你要确保它的作用域是正确的。为此,我使用了一个属性来确保这意味着我想要的。
@Component({
...
template: '<child [myCallback]="theBoundCallback"></child>',
directives: [ChildComponent]
})
export class ParentComponent{
public theBoundCallback: Function;
public ngOnInit(){
this.theBoundCallback = this.theCallback.bind(this);
}
public theCallback(){
...
}
}
@Component({...})
export class ChildComponent{
//This will be bound to the ParentComponent.theCallback
@Input()
public myCallback: Function;
...
}
在某些情况下,您可能需要由父组件执行业务逻辑。在下面的例子中,我们有一个子组件,它根据父组件提供的逻辑来呈现表行:
@Component({
...
template: '<table-component [getRowColor]="getColor"></table-component>',
directives: [TableComponent]
})
export class ParentComponent {
// Pay attention on the way this function is declared. Using fat arrow (=>) declaration
// we can 'fixate' the context of `getColor` function
// so that it is bound to ParentComponent as if .bind(this) was used.
getColor = (row: Row) => {
return this.fancyColorService.getUserFavoriteColor(row);
}
}
@Component({...})
export class TableComponent{
// This will be bound to the ParentComponent.getColor.
// I found this way of declaration a bit safer and convenient than just raw Function declaration
@Input('getRowColor') getRowColor: (row: Row) => Color;
renderRow(){
....
// Notice that `getRowColor` function holds parent's context because of a fat arrow function used in the parent
const color = this.getRowColor(row);
renderRow(row, color);
}
}
所以,我想在这里演示两件事:
胖箭头(=>)代替.bind(this)来保存正确的上下文;
子组件中回调函数的类型安全声明。
例如,我使用了一个登录模态窗口,其中模态窗口是父窗口,登录表单是子窗口,登录按钮调用了父窗口的关闭函数。
父模态包含关闭模态的函数。这个父组件将close函数传递给登录子组件。
import { Component} from '@angular/core';
import { LoginFormComponent } from './login-form.component'
@Component({
selector: 'my-modal',
template: `<modal #modal>
<login-form (onClose)="onClose($event)" ></login-form>
</modal>`
})
export class ParentModalComponent {
modal: {...};
onClose() {
this.modal.close();
}
}
在子登录组件提交登录表单后,它使用父模块的回调函数关闭父模块
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'login-form',
template: `<form (ngSubmit)="onSubmit()" #loginForm="ngForm">
<button type="submit">Submit</button>
</form>`
})
export class ChildLoginComponent {
@Output() onClose = new EventEmitter();
submitted = false;
onSubmit() {
this.onClose.emit();
this.submitted = true;
}
}
更新
这个答案是在Angular 2还处于alpha阶段的时候提交的,当时很多特性都无法使用/没有文档记录。虽然下面的方法仍然有效,但这种方法现在已经完全过时了。我强烈推荐下面接受的答案。
原来的答案
是的,事实上它是,但是你要确保它的作用域是正确的。为此,我使用了一个属性来确保这意味着我想要的。
@Component({
...
template: '<child [myCallback]="theBoundCallback"></child>',
directives: [ChildComponent]
})
export class ParentComponent{
public theBoundCallback: Function;
public ngOnInit(){
this.theBoundCallback = this.theCallback.bind(this);
}
public theCallback(){
...
}
}
@Component({...})
export class ChildComponent{
//This will be bound to the ParentComponent.theCallback
@Input()
public myCallback: Function;
...
}
以下是我在Angular 13中的工作(截至2022年3月)。
附注:这与其他人的回答或多或少有些相似。添加这个答案只是为了让人们知道它可以在Angular 13中工作。
在父组件中将函数定义为平箭头函数,而不是常规函数。
callBackFn= (args: string): void => {
// callback code here
// This will work (Flat Arrow)
}
// callbackFn(args: string): void {
// //This type of definition will not work.
// }
将回调函数作为属性传递给子组件
<app-child [callBack]=”callBackFn”></app-child>
在子组件中接收回调函数作为Input。该定义应该与父类中定义的定义相匹配。
@Input() callBack: (args: string) => void;
然后在子组件中调用该函数。你也可以称它为子组件模板。
this.callBack('Test');
OR
<button (click)="callBack('Test')"></button>
但不确定这种方法是否好。
我在ReactJS中看到了类似的方法,它工作得很好,但仍然不确定它在angular中是如何工作的,以及它的影响是什么。
请对这一办法提出任何意见。