Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 如何在不破坏封装的情况下调用子组件方法?_Angular_Typescript - Fatal编程技术网

Angular 如何在不破坏封装的情况下调用子组件方法?

Angular 如何在不破坏封装的情况下调用子组件方法?,angular,typescript,Angular,Typescript,我有基于供应商组件的自定义日期和时间选择器组件。 如果简化,它可以看起来是这样的: @Component({ selector: 'app-date-time-picker', template: ` <vendor-date-picker [(ngModel)]="date"></vendor-date-picker> <vendor-time-picker [(ngModel)]="time"></vendor-time-pi

我有基于供应商组件的自定义日期和时间选择器组件。 如果简化,它可以看起来是这样的:

@Component({
  selector: 'app-date-time-picker',
  template: `
    <vendor-date-picker [(ngModel)]="date"></vendor-date-picker>
    <vendor-time-picker [(ngModel)]="time"></vendor-time-picker>
  `
})
export class DateTimePickerComponent {
  @Output() timestampChanged = new EventEmitter<number>();

  date: string;
  time: string;

  reset() {
    this.date = "";
    this.time = "";
  }
}
@组件({
选择器:“应用程序日期时间选择器”,
模板:`
`
})
导出类DateTimePickerComponent{
@Output()timestampChanged=neweventemitter();
日期:字符串;
时间:字符串;
重置(){
this.date=“”;
这个时间=”;
}
}
我有一个使用DateTimePicker的父组件,有时需要将其重置为以下状态:

@Component({
  selector: 'app-parent',
  template: `
    <app-date-time-picker #dateTimePicker (timestampChanged)="updateDateTime($event)"></app-date-time-picker>
  `
})
export class Parent {
  @ViewChild('dateTimePicker') private _dateTimePicker: DateTimePickerComponent;

  someEvent() {
    this._dateTimePicker.reset();
  }
}
@组件({
选择器:“应用程序父级”,
模板:`
`
})
导出类父类{
@ViewChild('dateTimePicker')private _dateTimePicker:DateTimePickerComponent;
someEvent(){
这是.u dateTimePicker.reset();
}
}

我从供应商那里创建如此丑陋组件的原因(以及相关代码)超出了问题的范围。对我来说重要的是,使用ViewChild会破坏对子对象的封装。我不能使用“private”关键字(如“date”和“time”)保护其他子字段,因为它们在模板中使用。所以问题是angular是否有机制通过一些声明的公共接口(比如使用输入)调用child方法或者保护其他子组件字段在模板中仍然可用,但不能从外部访问?

父组件不会破坏
DateTimePickerComponent
封装-只要
reset
方法被认为是公共的。组件只是类实例,父组件可以访问其公共成员

考虑到父组件和子组件都是第一方组件,通常不存在实际的封装问题,因为开发人员通常知道组件的预期用途,但这对于更大的团队来说可能是一个问题

据我所知,这里的问题是,由于Angular AOT编译的工作方式,它在编译的模板中提供了类型安全性,但要求组件模板中使用的所有组件成员都是公共的,而组件模板和类可以被开发人员视为单个实体,这些成员实际上是私人的

一种选择是使用匈牙利符号,并在事实上私有的所有组件成员前面加下划线(这提供了,不管状态如何),包括组件模板中使用的成员。缺点是由于有大量带下划线的属性,模板的可读性变差。另一个缺点是,这种表示法无助于区分不应该在模板中使用的成员(例如,大多数注入服务)

另一个选项是提供组件,这些组件应具有相应的公共接口的公共成员:

interface IDateTimePickerComponent {
  reset();
}

export class DateTimePickerComponent implements IDateTimePickerComponent {
  @Output() timestampChanged = new EventEmitter<number>();

  date: string;
  time: string;

  reset() {
    this.date = "";
    this.time = "";
  }
}

当然,还有其他的,但它们不应该仅仅因为封装问题而成为首选。OOP原则的存在是为了指导和帮助开发人员,而不是为了跳转。

我只想使用
ViewChild
。我不知道你为什么认为它打破了封装视图孩子是非常适合你这种情况。使用它是可以的,私有字段不会受到影响,如果您有公共字段,则可以从其他classesOOP/SOLID后台访问它们。这就是为什么我认为这根本不好,这不是一个解释。我也看不到破坏。@HenkHolterman我认为OP意味着可能存在目前TS无法阻止的潜在封装破坏。你清楚地理解我所关心的。我真的不喜欢这样一个事实,即对于模板,字段不能是公共的,而对于外部使用,字段不能是私有的。是的,使用界面确实可以避免这个问题。
@ViewChild('dateTimePicker') private _dateTimePicker: IDateTimePickerComponent;