Angular - @Input и @Output vs. Injectable Service - PullRequest
0 голосов
/ 25 июня 2018

Я спрашиваю себя, где различия между @Input / @Output в родительских / дочерних компонентах и , использующих сервисы, которые только один раз устанавливаются с зависимостью Injection @Injectable().Или есть какие-то различия, кроме того, что ввод / вывод можно использовать только в родительском / дочернем компе.

Следующий пример для лучшей визуализации:

с @Input:

<parent-comp>
   <child-comp [inputFromParent]="valueFromParent"></child-comp>
</parent-comp>

ChildComponent:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  @Input() public inputFromParent: string;
}

С внедрением зависимости

@Injectable()
export class Service {
   private value: string;

public get value(): string {
   return value;
}

public set value(input): void {
   value = input;
}

}

Теперь мы можем установить значение в родительском комп.и получить значение в дочернем компе с инъекцией зависимости.ChildComponent:

@Component({
  selector: 'child-comp',
  template: ...
})
export class ChildComponent {
  private value: string;
  constructor(private service: Service) {
  this.value = this.service.getValue;
}

}

Несмотря на то, что первый подход выглядит проще, я распознал использование 3-4 свойств, переносимых через родительский / дочерний комп.с @Input / @Output делает образец очень запутанным и неуклюжим.

1 Ответ

0 голосов
/ 25 июня 2018

Не совсем вопрос с определенным ответом, но ....

@Input и @Output полезны, если общение между родителем и ребенком является только между родителем и ребенком. Не имеет смысла иметь службу, которая поддерживает одноэлементные данные только для 2 компонентов (или каковы бы ни были глубоко вложенные элементы grandparent -> parent -> child).

Они также полезны, если ваш родитель должен реагировать на изменения в ребенке. Например, нажав кнопку в дочернем компоненте, который вызывает функцию в родительском компоненте:

<my-child-component (myOutputEmitter)="reactToChildChange($event)"></my-child-component>

А у родителя:

reactToChildChange(data: any) {
  // do something with data
}

Если вы передаете много свойств @Input дочернему элементу и хотите привести в порядок шаблон, то вы можете определить интерфейс для ввода и передать его взамен. например,

export interface MyChildProperties {
   property?: any;
   anotherProperty?: any;
   andAnotherProperty?: any;
}

Затем вы можете передать своему ребенку определение, которое устанавливается родителем:

childProperties: MyChildProperties = {
    property: 'foo',
    anotherProperty: 'bar',
    andAnotherProperty: 'zoob'
}

Тогда ваш дочерний компонент может иметь:

@Input properties: MyChildProperties;

и ваш шаблон становится:

<my-child-component [properties]="childProperties"></my-child-component>

Ваш ребенок может получить доступ к этим свойствам с properties.property, properties.anotherProperty и т. Д.

Чистота, порядок, и ваши данные теперь содержатся в тех компонентах, которые должны взаимодействовать.

Однако службы следует использовать там, где более чем одному компоненту требуется доступ для чтения / записи данных по всему вашему приложению. Рассмотрим, например, UserService, когда множество различных компонентов должны иметь доступ к текущему вошедшему в систему пользователю. В этом случае служба является разумной, как единичный, поэтому после того, как вы настроили зарегистрированного пользователя, любые компоненты, которые внедряют UserService, могут получить доступ к его данным и функциям.

Точно так же, если бы вы использовали службу для реагирования на изменения, вы бы обнаружили, что пишете службы с наблюдаемыми, чтобы ваши компоненты могли подписаться на изменения в данных. Eventemitters уже дают вам этот шаблон с @Output, как показано выше.

Если бы это был простой родитель -> дочернее общение, это ненужные накладные расходы, и его следует избегать.

Тем не менее, если вы обнаружите, что используете службы для управления глобальным состоянием, вам лучше использовать некоторую форму управления состоянием, такую ​​как ngrx

...