Угловое 2+/4/5: интеллектуальное, немое и глубоко вложенное компонентное сообщение

ПРИМЕЧАНИЕ. Для простоты рассмотрите глубину компонента как:

- Smart (grand)parent level 0
  - dumb child level 1
   ....
    - dumb grandchild level 2
      ....)

Существуют различные варианты и условия взаимодействия между интеллектуальными/грандиозными/родительскими/дочерними компонентами и передачей данных вверх и вниз по цепочке MULTI-LEVEL (не менее 3-х уровней). Мы хотели бы, чтобы наш "умный" (грандиозный) родительский компонент был единственным компонентом, который имеет доступ к нашей службе данных (или атомному/неизменяемому магазину), и это приведет к обмену информацией с "немыми" (большими) детьми. Возможные варианты:

  1. Анти-шаблон (?) : Передача данных вниз и вверх по цепочке компонентов с помощью @Input/@Output bindings. Это то, что некоторые называют проблемой "посторонних свойств" или "проблема барботирования пользовательских событий" (например, здесь и здесь.). Нет.
  2. Анти-шаблон: доступ к интеллектуальным компонентам для немых (больших) детей через @ViewChildren или @ContentChilden. Это снова затрудняет работу детей и по-прежнему не создает чистого механизма для (больших) детей для передачи данных UP к интеллектуальному компоненту.
  3. Общая служба сообщений, описанная в кулинарной книге angular.io здесь, и отличный пост здесь.
  4. ?

Теперь в случае "3" у немых (грандиозных) детей должна быть введена служба сообщений. Это подводит меня к моим вопросам:

Q1: Кажется интуитивно странным для каждого из "немых" (внушительных) детей, чтобы вставлять сообщение. Является ли наилучшей практикой для службы сообщений быть специализированным сервисом для этого семейства или делает ли это копирование службы данных, которую "умный" дед и бабушка обвиняется в упомянутом выше?

Q1A: Кроме того, как это намного лучше, чем добавление привязок @Input/@Output вверх и вниз по цепочке, если у всех компонентов будет введенная услуга? (Я вижу аргумент, что "немой" компонент нуждается в некотором способе получения информации)

Q2: Что, если "умный" великий родитель общался с магазином, подобным редуксу (ngrx для нас)? Опять же, общение с "немыми" компонентами лучше всего происходит с помощью службы ввода/выделенного сообщения или лучше всего вводить хранилище в каждый "немой" компонент... или? Обратите внимание, что межкомпонентная связь представляет собой комбинацию "действия" (например, подтверждение формы, кнопка отключения и т.д.) В дополнение к данным (например, добавление данных в /update store или service).

Мысли очень оценили!

Ответ 1

Поэтому, изучив это дальше, когда дело доходит до того, как лучше всего общаться вниз и вверх по вложенной цепочке компонентов, похоже, действительно есть только два варианта: фаустовская сделка между:

  • либо передайте привязки @Input/@Output вверх, вниз и всюду по всей вложенной цепочке компонентов (т.е. справитесь с проблемами "персонализации событий" или "посторонних свойств")

ИЛИ ЖЕ

  • Используйте службу обмена сообщениями/подписки для связи между этим семейством компонентов (отличное описание здесь) и введите эту услугу для каждого компонента в цепочке.

Я лично выступаю за использование умных и презентационных ("немых") компонентов. Номинально для "немого" компонента нужны только @Inputs и @Outputs и это. Не важно, насколько глубоко или неглубоко в дереве компонентов - проблема приложений. На самом деле все равно, какое приложение использует его в первую очередь. Между тем, глубокий компонент не очень тупой или переносимый, если в него вводится конкретная служба. BTW, компонент "умный" контр-части действительно предоставляет посреднические услуги (через первый класс @Injectable service или редукционно-подобный магазин) независимо от того, какой немой компонент в его генеалогическом дереве нуждается в нем. Интеллектуальный компонент также не заботится о компонентах, находящихся за пределами его непосредственных дочерних @Inputs, пока внуки каким-то образом сигнализируют о действиях службы, которые необходимо предпринять (опять же через цепочку @Input/@Output). Таким образом, интеллектуальный компонент также становится переносимым по линиям приложений.

Учитывая это, сделка Фауста, IMO, опирается на использование цепочки @Input/@Output со всеми упомянутыми проблемами, которые она несет с собой. Тем не менее, я слежу за этим и приветствую чистые и развязанные альтернативы, если кто-нибудь знает.

Ответ 2

Почему № 1 - анти-шаблон? Компонент grandparent владеет данными и передает их немым дочерним компонентам через параметры @Input. Немые дочерние компоненты просто вызывают обратные вызовы при возникновении события (через эмитенты событий @Output), заставляя компонент grandparent манипулировать данными. Кажется чистым для меня.

Изменение: я вижу вашу точку зрения о многократном переносе значений, таких как обработчик отправки через многие промежуточные уровни. Возможно, в родительском компоненте может быть создана вложенная структура, которая представляет ваше дерево компонентов. Затем каждому компоненту можно передать необходимые ему свойства, а также передать объект другому компоненту. Затем каждый компонент знает только о том, что ниже:

// Parent component builds this object (or gets a service to do it)

viewModelForChildComponent: {

    property1NeededForChildComponent,

    property2NeededForChildComponent,

    viewModelForGrandChildComponent: {
        property1NeededForGrandChildComponent,

        property2NeededForGrandChildComponent,

        viewModelForGrandGrandChildComponent: {
            property1NeededForGrandGrandChildComponent,

            submitHandlerNeededForGrandGrandChildComponent
        }
    }
}

Ответ 3

Связи Input() и Output() также являются совершенно законным способом справиться с этим. Пусть интеллектуальный компонент обрабатывает логику генерации значений, а затем использует Input() и Output(), чтобы просто передавать и получать значения по цепочке компонентов.

Конечно, это указывает на один из недостатков подхода smart/view: больше файлов; более шаблонный. Вот почему я бы не стал спорить об одном подходе, который подходит для одного размера. Скорее, выберите подход, который имеет смысл в вашем текущем контексте (как для приложения, так и для вашей организации).