Рубрики
Без рубрики

Компонентное взаимодействие в угловом угловом

Прочитайте это всеобъемлющее руководство по которым различные формы коммуникационной работы и как их использовать в угловом углу.

Автор оригинала: Kevin Farst.

Одним из более интересных тем для погружения в угловую, сравнивающую и контрастирующую способов направлений и компонентов взаимодействовать друг с другом в обоих OG Angular.js (ingular 1.x) и новые версии (2+).

Ради упрощения вещей, я буду ссылаться на угловые 1.x как angular.js и версию 2 и выше как угловой. В более новых версиях угловых, определенные среды коммунации были перенесены – некоторые избаковкивающиеся с одинаковыми основными концепциями, и некоторые компоненты новых методов могут использовать для связи друг с другом.

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

Стол содержания

  • Привязки ввода
  • Выходные привязки
  • Местный шаблон переменной
  • ViewShild и CondentChild.
  • ViewShildren и CondentChildren.
  • Общение через сервис
  • Заключение

Привязки ввода

Это основной способ пропускания значений в компонент. Если вы когда-нибудь имели дело с охватом изолята или использовали BindTocontroller Синтаксис в Angular.js, концепция одинакова: значения передаются в директиву через HTML атрибуты.

bvwslwf.png.

С приведенным выше примером Angular.js у нас было несколько вариантов того, как мы хотели пройти эти ценности в директиву.

  • Двухстороннее связывание ( = ) – изменения, сделанные на значение внутри Директивы, будут отражены на объекте за пределами Директивы, а также Vise Versa
  • Односторонняя связывание ( & ) – изменения в стоимости могут быть переданы только в директиву, и любые изменения внутри Директивы не повлияют на значение за пределами контекста Директивы
  • Привязка текста ( @ ) – значение передается как текстовое значение

С @Input () Декоратор в более поздних версиях угловых значений, передаваемых в HTML-атрибуты, доступны внутри Компонент переменной сопоставлением имени атрибута.

3d1vyxx.png.png.png

Интерфейс заканчивается быть более простым, однако имейте в виду, что это только одностороннее привязка, то есть В родительском компонентных отношениях любые изменения сделаны для @Input () Переменная внутри ребенка не будет отражается в родительском компоненте. Мы можем установить двустороннюю связь с родителем с использованием @Output () декоратор.

Выходные привязки

Одним из них следует помнить, так это то, что при добавлении компонента к DOM экземпляр его класса создается, соответствующий тому тему, вставленному в HTML. Когда это произойдет, экземпляр класса имеет API, который можно взаимодействовать с на основе модификаторов доступа, прикрепленных к переменным класса и методам. Поэтому, если у нас есть компонент

  ...
  export class ParentComponent {
    public visibleVar: string = 'variable';
    private hiddenVar: integer = 23;

    public myMethod() {
      ...
    }
  }

Когда экземпляр ParentComponent Создан, мы сможем получить доступ к Visiblevar и mymethod () , но не Hiddenvar во внешнем классе, будь то услуга, другой компонент и т. Д. Это приводит нас к @Output () декоратор, который позволяет нам проходить (публично) метод от родительского компонента до дочернего компонента. Оттуда дочерний компонент может позвонить метод при необходимости. Это то, как проводится двусторонняя связь между родительским и дочерним компонентом.

Например, скажем, у нас есть ChoineComponent и а Moviedetailscomponent , в котором MovieComponent состоит списка Moviedetailscomponent экземпляры. Если бы мы хотели предупредить ChoineComponent Когда экземпляр Moviedetailscomponent был помечен как любимый пользователем (возможно, нажав кнопку или флажок), это может выглядеть что-то подобное:

// Parent component
export class MoviesComponent {
  movies: Movie[];
  ...
  toggleAsFavorite(detailCmp: MovieDetailsComponent) {
    detailCmp.isFavorited = !detailCmp.isFavorited;
  }
}

// Child component
export class MovieDetailsComponent {
  @Input('movie') movieData: Movie;
  @Output() toggleAsFavorite = new EventEmitter();
  ...
}

И в ChoineComponent Вид шаблона:



Как с @Input () Декоратор, мы подходим @Output () Имя переменной к атрибуту HTML, затем пропустите метод от ChoineComponent в Moviedetailscomponent Отказ Основное отличие от @Input () Переменная декларация такое, как и что Мы создали его. С @Input () Переменная, вы можете выбрать его значение по умолчанию или просто оставить его как пустой заполнитель (как мы сделали выше). С @Output () , вам нужно создать новый экземпляр встроенного углового класса под названием Eventemitter , который используется компонентами для излучения пользовательских событий.

В этом текущем примере, когда мы называем метод, мы также передаем аргумент, который является Moviedetailscomponent сам экземпляр. Из-за этого Я решил объявить Eventemitter Однако вы можете просто просто использовать Eventemitter <> Особенно, если вы не передаете аргумент на метод, который будет называться. Отсюда, ссылается на переменную и звоню Эмит () На нем будет выполняться метод, так что в нашем случае мы делать это внутри Moviedetailscomponent Шаблон Когда пользователь нажимает ссылку.

С комбинацией @Input () и @Output () Декораторы, это рефлексию реактированной мантры, в которой

События текут, данные потоки

Данные передаются с помощью @Input () Декоратор, в то время как событие испускается через @Output декоратор. Разоблачение части Pubic API от родительского компонента к дочернему компоненту напоминает требуется Ключ используется в Angular.js. От Angular.js Документы

...
.directive('myTabs', function() {
  return {
    ...
    controller: ['$scope', function MyTabsController($scope) {
      ...
      this.addPane = function(pane) {
        if (panes.length === 0) {
          $scope.select(pane);
        }
        panes.push(pane);
      };
    }],
    ...
  };
})
.directive('myPane', function() {
  return {
    require: '^^myTabs',
    ...
    link: function(scope, element, attrs, tabsCtrl) {
      tabsCtrl.addPane(scope);
    },
    ...
  };
});

Любая функция или свойство набора на это В родительской директиве контроллер можно было бы получить доступ в дочерней директиве сочетанием прохождения Во имя родительской директивы в качестве значения для требуется Ключ в объекте определения Директивы ребенка, затем прохождение этого контроллера в Как четвертый аргумент для ссылка функция.

Еще одна вещь, которую следует отметить, вы, вероятно, заметили #movedetails атрибут на <Детали фильма> Компонентная тег, и что она передается в Функция, что @Output () Декоратор в конечном итоге Эмит () Отказ Давайте посмотрим на еще одну форму взаимодействия компонентов.

Местный шаблон переменной

Хотя мы проезжаем фильм Объект от родителя ChoineComponent к экземпляру Moviedetailscomponent это не дает Родительский компонентный доступ к любой из остальных публичных API дочернего компонента. Если ChoineComponent Хочет доступ к общественной собственности или общественный метод на Moviedetailscomponent , это должно сделать это с помощью Локальная переменная Отказ Поэтому, когда мы добавляем #movedetails Переменная шаблона на <Детали фильма> тег, и потому что тег находится внутри ChoineComponent Шаблон, это дает нам ссылку Для дочернего компонента и способности доступа к любой его свойства или методы изнутри родительского шаблона. В этом случае мы делаем это от Передача его в метод на родительском компоненте.



ViewShild и CondentChild.

Местный шаблон Variable Apporach работает хорошо, когда вам нужен доступ к общедоступному доступу к публичному API дочернего компонента в шаблоне (мы передвигаемся, пройдя ссылка на функцию @Output () Функция и излучающая его как событие) Отказ Вы не можете использовать технику, если экземпляр ChoineComponent сам класс (не его шаблон) необходимо прочитать или запись значений дочерних компонентов, или если родительский компонент должен иметь возможность напрямую позвонить методам дочерних компонентов. Для этого вы можете либо использовать @Viewchild () или @ContentChild () декоратор. Хотя они используются в слегка разных контекстах, имейте в виду что они оба позволяют получить доступ к общедоступным API дочернего компонента (свойства и методы) в экземпляре класса родительского компонента, как и локальная переменная делает в шаблоне родительского компонента. Давайте посмотрим, как каждый декоратор отличается.

Вид на ребенка

Этот декоратор используется, когда HTML-тег дочернего компонента объявляется внутри шаблона родительского компонента, что означает <Детали фильма> Тег придется быть добавленным внутри ChoineComponent шаблон. Оттуда вам нужно добавить переменную для ссылки API дочернего компонента внутри родителя.

// Parent component
export class MoviesComponent {
  ...
  @ViewChild(MovieDetailsComponent)
  private movieDetailsComponent: MovieDetailsComponent;
}

Существует одна дополнительная предостережения по сравнению с местной переменной техникой в том, что КиноDetailsComponent Переменная будет только установлена После инициализации представления Отказ Нам нужно погрузиться в список Крючки жизненного цикла и вытащить Refterviewnit интерфейс. Как только интерфейс реализован на нашем родительском компоненте, мы можем добавить ngafterviewinit () Метод, где мы наконец-то имеем доступ к moviedetailscomponent имущество.

// Parent component
export class MoviesComponent implements AfterViewInit {
  ...
  @ViewChild(MovieDetailsComponent)
  private movieDetailsComponent: MovieDetailsComponent;
  ...
  ngAfterViewInit () {
    this.movieDetailsComponent.someChildMethod();
  }
}

Содержание ребенка

С @ContentChild () Декоратор, доступа к API дочернего компонента, когда HTML-тег дочернего компонента объявлен между Открытие и закрытие меток тег HTML родительского компонента. Для нашего ChoineComponent и Moviedetailscomponent это будет выглядеть

  
    
  

И снова свойство Component Component не устанавливается в инициализации родительского компонента. В этом случае это будет после Содержание инициализируется, поэтому мы будем использовать Aftercontentinit Вместо того, чтобы крючок жизненного цикла.

// Parent component
export class MoviesComponent implements AfterContentInit {
  ...
  @ContentChild(MovieDetailsComponent)
  private movieDetailsComponent: MovieDetailsComponent;
  ...
  ngAfterContentInit () {
    this.movieDetailsComponent.someChildMethod();
  }
}

ViewShildren и CondentChildren.

Эти декораторы служат той же цели, что и их @Viewchild () и @ContentChild () Ассортимент, за исключением того, что они обеспечивают доступ к нескольким дочерним компонентам одного типа. Это может быть использовано В нашем первом Moviedetailscomponent Пример, где мы итариваемся в список фильмов с NGFOR цикл для вывода нескольких экземпляров в поле зрения. При определении А @Viewchildren () или @ContentChildren () Однако переменная в родительском компоненте, поэтому давайте посмотрим на пример.

// Parent component
export class MoviesComponent implements AfterViewInit {
  ...
  @ViewChildren(MovieDetailsComponent)
  private movieDetails: QueryList;
  ...
  ngAfterViewInit () {
    this.movieDetails.changes.subscribe(changes => console.log(changes));
  }
}

Вы заметите, что переменная типа QueryList , который имеет недвижимость на нем, изменения , что можно подписаться на. Что делает QueryList Интерфейс так приятно, когда состояние приложения Изменения, угловые, автоматически обновляют список дочерних компонентов, и вы можете подписаться на эти изменения с момента изменения Свойство возвращает Наблюдаемый Отказ

Общение через сервис

Один из способов компонентов может взаимодействовать друг с другом, у которого есть такая же основная концепция, как Angular.js, но Был переупакован с немного другим интерфейсом использует услугу для обмена данными. Услуги – это утилита Модуль углового модуля, и один из способов использования, чтобы обеспечить наблюдаемый Тема Для каких компонентов могут отправлять значения, и другие компоненты, которые подписались на наблюдаемый, могут получить. Пример! Использование фильма, избирающего использование корпуса сверху, давайте Сказать каждый Moviedetailscomponent Экземпляр имеет маленькую звезду, вы можете нажать на «любимый» фильм вместо ссылки. Любимый счет будет Затем появляйтесь в правом верхнем углу, когда вы продолжите выбирать фильмы в качестве избранного.

Lixifgy.gif.

Во-первых, давайте настроим Favoritesservice , где мы используем Тема Источник как частная собственность, затем публично разоблачить как Наблюдаемый Отказ

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class FavoritesService {
  private countSource = new Subject();

  count = this.countSource.asObservable();

  updateCount(count: number) {
    this.countSource.next(count);
  }
}

Когда фильм является благоприятным, событие передается на ChoineComponent (Звучит знакомый? Это был пример привязки выхода), Что имеет ссылку на Favoritesservice пример. Оттуда он собирает счет всех фильмов, которые были извлечены в соответствии с QueryList Ссылка, то звонит UpdateFavoriteCount () Итак, Тема Знаю, чтобы отправить следующее значение (обновленное избранное количество фильмов) всем его подписчикам.

...
export class MoviesComponent {
  @ViewChildren(MovieDetailsComponent)
  private movieDetails: QueryList;
  ...
  constructor(private favoritesService: FavoritesService) { }
  ...
  updateFavoriteCount() {
    this.favoritesService.updateCount(
      this.movieDetails.filter(comp => comp.isFavorited).length
    );
  }
}

ToolbarComponent подписывается на эту услугу, как мы видим ниже. Две вещи, чтобы отметить здесь:

  • Favsub Собственность подписана на Считать Собственность, не CountSource имущество. Так как CountSource это Частный У нас нет доступа к нему здесь в любом случае, но главное Считать Собственность – это то, что открывает CountSource как Наблюдаемый пример
  • Любой Подписка Экземпляры, которые вы создаете где угодно Должен иметь Отписаться () вызвал их, когда вы закончите с этим чтобы не вызывать утечку памяти
...
export class ToolbarComponent {
  favSub: Subscription;
  favoritesCount: number = 0;

  constructor(private favoritesService: FavoritesService) { }

  ngOnInit() {
    this.favSub = this.favoritesService.count.
      subscribe(favoritesCount => this.favoritesCount = favoritesCount);
  }

  ngOnDestroy() {
    this.favSub.unsubscribe();
  }
}

Заключение

Даже если вы рассмотрели подобные посты в блоге или охватывании материала, охватывающие компонент и директирующие общение в угловой, я надеюсь, что вы нашли полезную информацию из этой статьи или, по крайней мере, У некоторых из этих концепций описаны новым уникальным способом для вас. Опять же, вы можете найти некоторые из примеров, используемых в этом Образец углового приложения , что я определенно рекомендую вам делать, если вы все еще знакомятся с импортными модулями, реализующие интерфейсы и т. Д. Я оставил все, кроме необходимого кода в каждом фрагменте Чтобы продемонстрировать концепции, но вы найдете эти недостающие части в репо. Не стесняйтесь публиковать какие-либо вопросы или комментарии ниже, а как всегда счастливые кодировки!