【问题标题】:Passing function to child component, wrong context of 'this'将函数传递给子组件,“this”的上下文错误
【发布时间】:2018-01-23 05:41:51
【问题描述】:

我正在尝试将函数传递给子组件。传递函数工作正常。问题是,如果我想更改父组件的属性值,这将不起作用,因为“this”不是引用父组件,而是引用子组件(在我的情况下为 DatagridComponent)

this 的上下文似乎是问题所在。请参阅下面代码中的 cmets。

父组件:

@Component({
  selector: 'app-user-management',
  templateUrl: './user-management.component.html',
  styleUrls: ['./user-management.component.css'],
})
export class UserManagementComponent implements OnInit {
  showUserDetails: boolean: false;
  showUsergroupDetails = false;

  onSelectUser() {
    this.showUsergroupDetails = false;
    this.showUserDetails = true;
    console.log(this.showUsergroupDetails); // prints false, as expected
    console.log(this.showUserDetails); // prints true, as expected
    console.log(this); // prints DatagridComponent :(
}

HTML,将 onSelectUser 作为函数传递:

<app-datagrid [onSelection]="onSelectUser"></app-datagrid>

子组件:

@Component({
  selector: 'app-datagrid',
  templateUrl: './datagrid.component.html',
  styleUrls: ['./datagrid.component.css']
})
export class DatagridComponent implements OnInit {
  @Input() onSelection: () => {};

  onSelectListItem(item: any) {

    // some code

    if (this.onSelection) {
      this.onSelection(); // is executed, results see comments in parent component
    }
  }
}

子组件的HTML:

<div *ngFor="let item of items" (click)="onSelectListItem(item)">
   ....
</div>

我怎样才能做到这一点?

【问题讨论】:

  • 你可能想看看Component Interaction 文档,有很多不同的方式来实现父子组件之间的交互

标签: angular typescript


【解决方案1】:

使用Output 事件从子组件到父组件通信。使用Input 属性绑定将数据从parent 传递给孩子

HTML

<app-datagrid (onSelection)="onSelectUser($event)"></app-datagrid>

组件

@Component({
  selector: 'app-datagrid',
  templateUrl: './datagrid.component.html',
  styleUrls: ['./datagrid.component.css']
})
export class DatagridComponent implements OnInit {
  @Output() onSelection: EventEmitter<any> = new EventEmitter();

  onSelectListItem(item: any) {
     this.onSelection.emit(item);
  }
}

//app-user-management method will receive item object
onSelectUser(item: any) {
   //here you would have item object.
}

另见Component Interaction

【讨论】:

  • 感谢您的回复。不幸的是,在this.onSelection.emit(item) 我收到一个错误:TS2349:Cannot invoke an expression whose type lacks a call signature. Type 'EventEmitter&lt;any&gt;' has no compatible call signatures. 知道为什么这不起作用吗?
  • 没关系,忘了去掉括号。所以this.onSelection.emit(item) 代替this.onSelection().emit(item) 起作用。谢谢。
【解决方案2】:

这个问题更多是关于this 上下文,你可以这样解决它:

onSelectUser = ()=>{ // note this part 
    this.showUsergroupDetails = false;
    this.showUserDetails = true;
    console.log(this.showUsergroupDetails); // prints false, as expected
    console.log(this.showUserDetails); // prints true, as expected
    console.log(this); // prints DatagridComponent :(
}

我们使用粗箭头将当前组件的上下文保持在函数内

【讨论】:

  • 这应该是公认的答案,因为它直接解决了问题。在子组件是外部库的一部分的情况下,这是实现此目的的唯一方法(没有双关语)。例如,Angular Material CDK (7.0.1) 充满了诸如此类的回调。
猜你喜欢
  • 2011-04-07
  • 2014-06-02
  • 1970-01-01
  • 2019-10-17
  • 2018-07-02
  • 2020-12-13
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
相关资源
最近更新 更多