#angular
Вопрос:
Рассмотрим этот упрощенный компонент:
test.component.html
<button>{{buttonData}}</button>
test.component.ts
import {Component} from '@angular/core';
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css']
})
export class TestComponent {
buttonData: string = 'Test';
changeButtonContents(data) {
this.buttonData = data;
}
}
Теперь, рассматривая этот другой компонент:
other.component.html
<app-test></app-test>
Каков наилучший способ предоставления «API» из app-test
компонента? Под API я подразумеваю вызываемые методы и настраиваемые переменные. Насколько я знаю, мы можем передавать переменные только как [property]='bindings'
Одним из способов было бы @ViewChild
это сделать, но это «кажется» неправильным, и это также дает полный доступ к компоненту, в отличие от предоставления API.
Ответ №1:
Вы не предоставляете «API» (я буду использовать его как термин, чтобы вы лучше понимали, но он неверен), вы можете просто передавать параметры от «Родителя к ребенку» или «От ребенка к родителю» или даже отключенные компоненты (два, которые не являются «Родителем/ребенком», но вам нужно, чтобы параметр из A был получен на B).
В случае @ViewChild
, это способ, которым вы можете «устанавливать/обрабатывать» информацию на основе установленного вами «обработчика», чтобы вы могли контролировать определенную информацию, например nativeElement
.
Для родителя, как вы сказали [property]="'value'"
, и внутренне вы используете @Input()
Таким образом, в данном случае @Input()
относится к значению, которое компонент получает от родителя, и , с другой стороны, у вас есть @Output
, поэтому дочерний элемент может отправлять значения родителю.
Наконец, в третьем случае вы можете использовать в BehaviorSubject
сочетании со службой, чтобы «прослушивать» события, а затем подключать два компонента, которые не имеют таких отношений, как:
<app-my-general-component>
<component-a></component-a>
<component-b></component-b>
</app-my-general-component>
Так <component-a>
что можете общаться с <component-b>
Наконец, если вам нужно использовать определенную функцию, которая может изменять значения в другом компоненте, то сделайте это с помощью служб, а не самих функций компонента, и подключите оба через эту службу.
Итак, вот и все, в заключение:
- Если вам нужно, чтобы ребенок получал информацию от родителя, используйте
@Input()
- Если вам нужно, чтобы ребенок отправлял информацию родителю, используйте
@Output()
- Если вам нужны два компонента для подключения, используйте
BehaviourSubject
Проверьте официальные документы: https://angular.io/guide/inputs-outputs
Ответ №2:
Почему вы думаете, что подход @ViewChild не очень хорош? Возьмем пример кнопки «Материал». В нем есть метод, называемый focus()
, с помощью которого потребители могут сфокусировать кнопку мата.
Теперь, как сделать метод фокусировки вызова потребителя? Используете ViewChild правильно?
<button mat-raised-button color="primary" #btnRef="matButton">{{'recovery' | translate}}</button>
В файле компонента
@ViewChild('btnRef') buttonRef: MatButton;
ngAfterViewInit() {
this.buttonRef.focus();
}
Возьмем другой пример выбора материала, у него есть открытый метод:
<mat-select #mySelect placeholder="Favorite food">
<mat-option *ngFor="let food of foods" [value]="food.value">
{{ food.viewValue }}
</mat-option>
</mat-select>
Как мы получаем доступ к API?
...
@ViewChild('mySelect') mySelect;
...
click() {
this.mySelect.open();
}
Поэтому, на мой взгляд, можно использовать метод API компонентов с помощью ViewChild. Вот как мы захватываем экземпляр компонента и вызываем метод API.