g1er / Andrew

0 stars 0 forks source link

Взаимодействия между компонентами #35

Open IgorKulishov opened 5 years ago

IgorKulishov commented 5 years ago

1. Рассмотрим передачу от родительской к дочерней компоненте:

A. Enclosed components structure/scheme:

<parent-component *ngFor="let hero of heroes">
     <child-component [hero]="hero">
     </child-component>
</parent-component>

This is how we pass simple object hero with only name property from Parent to Child component. Родительская компонента имеет несколько вложенных дочерних компонент (созданых с помощью циклического оператора ngFor). Дочерняя компонента принимает объект hero через оператор [hero]=, при этом значение родительского объекта справа от знака равенства внутри ковычек "hero".

B. Parent component

import { Component } from '@angular/core';
@Component({
  selector: 'parent-component',
  template: `<child-component [hero]="hero">
             </child-component>`
})
export class ParentComponent {
  heroes = [
    { "name": "Winnie Pooh"},
    { "name": "Piglet" }
  ];
}

Родительская компонента включает в template: дочернюю компоненту и показывает как будет происходить передача значения объектов от родительской к дочерней компоненте.

C. Child component

import { Component, Input } from '@angular/core';
@Component({
  selector: 'child-component',
  template: `<div>{{hero.name}}</div>`
})
export class ChildComponent {
  @Input() hero: {name: string;};
}

Дочерняя компонента содержит:


2. Рассмотрим передачу от дочерней к родительской компоненте:

A. Enclosed components structure/scheme:

<parent-component *ngFor="let hero of heroes">
     <child-component [hero]="hero" (selectedHero)="onSelectHero($event)">
     </child-component>
</parent-component>

Все тоже самое, только мы добавили (selectedHero)="onSelectHero($event)" для передачи объекта от дочерней к родительской компоненте. Дочерняя компонента передает объект через (selectedHero) слева от знака равенства, при этом вызывается метод родительской компоненты и передается объект $event внутри метода "onSelectHero($event)".

B. Parent component

import { Component } from '@angular/core';
@Component({
  selector: 'parent-component',
  template: `<child-component [hero]="hero"  (selectedHero)="onSelectHero($event)">
             </child-component>
             <div>{{selectedHero.name}}</div>`
})
export class ParentComponent {
  selectedHero : {name: string} = undefined;
  heroes = [
    { "name": "Winnie Pooh"},
    { "name": "Piglet" }
  ];
  onSelectHero(hero): void {
    this.selectedHero = hero;
  }
}

Родительская компонента включает в template: дочернюю компоненту и показывает как будет происходить передача объекта от дочерней к родительской компоненте при помощи выражения (selectedHero)="onSelectHero($event)", где справа от знака равенства указывается метод родительской компоненты с параметром внутри скобок.

C. Child component

import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
  selector: 'child-component',
  template: `<button (click)="selectHero()">{{hero.name}}</button>`
})
export class ChildComponent {
  @Input() hero: {name: string;};
  @Output() selectedHero  = new EventEmitter<{name: string;}>();
   selectHero() {
     this.selectHero.emit(this.hero);
  }
}

Дочерняя компонента содержит:

g1er commented 5 years ago

От родителя к дочернему компоненту в принципе понятно. Но вот от дочернего к родителю.... никак не могу въехать, пытаясь разобраться, я запутываюсь еще сильнее. От этого начинаю беситься, и голова вообще отказывает... (( Я даже не могу толком сформулировать, что именно меня путает. Вообще, изначально, откуда все начинается? От selectedHero? Тогда почему он определяется в родительском компоненте, как и метод onSelectHero, а говорится, что передается из дочернего в родительский? selectHero и там, и там (и в родителе, и в дочернем). И там, и там с ним происходят изменения, поэтому я не могу понять, что первично, откуда начинается передача, с какого компонента, с какого момента делается 1й шаг, куда шагает операция дальше, и где это все заканчивается. В общем, у меня мозг закипает, не могу толком понять, от чего отталкиваться.

IgorKulishov commented 5 years ago

Прежде всего ни ты первый последний. Не даром говорят - "грызть гранит науки". Надо не забывать, что Angular это темплейтный язык и именно понимать его довольно сложно именно за счет добавленных темплейтных выражений (проще запоминать). Чувство когда трудно объяснить что не понятно мне тоже знакомо и как ни странно чаще возникает именно с Angular. Именно по этой причине программистам становиться сложно его осваивать, а тем более тем кто пришел с других языков им приходиться и работать и учиться осваивая находу. Именно за счет этого начинают набирать популярность другие фреймворки javascript vue.js, react.js

Тем не менее постараемся разобраться c Angular - думаю нам удасться разгрысть большую его часть - только надо набраться терпения немного и добавить практики (тут дело привычки, через какое-то время перестаешь спрашивать и все становиться привычным).

И так для начала я предлагаю посмотреть еще одно видео на русском языке https://www.youtube.com/watch?v=LV1x2X_QMVU.

А тем временем я подготовлю объяснение. Терпение и труд все перетрут! Удачи и терпения Бро! Все будет получаться, только надо время что бы разобраться и попрактироваться.

IgorKulishov commented 5 years ago

Далее я подготовлю объяснения по двум пунктам: 1) как выглядят вложеные компоненты (наглядно в режиме дебага на первой закладке : html) 2) как передаются события от дочерней компоненты к родительской при помощи EventEmitter (typescript) Напиши, если есть и другие вопросы.

IgorKulishov commented 5 years ago

1. как выглядят вложеные компоненты в html в режиме дебаг. Если рассмотреть пример выше (2.А.) и гипотетически построить приложение и потом его рассмотреть в дебагере в первой закладке Elements, то можно увидеть примерно следующую "матрешку" вложеных тэгов:

<parent-component *ngFor="let hero of heroes">
     <child-component [hero]="hero" (selectedHero)="onSelectHero($event)">
           <button (click)="selectHero()">{{hero.name}}
           </button>
     </child-component>
</parent-component>

Конечно же мы не увидем следующие элементы, поскольку они будут заменены на значения объектов определенных внутри ts кода внутри компоненты:

Так же мы не увидем:

Однако мы увидем самую последную матрешку, а именно html элементы дочерней компоненты

<button (click)="selectHero()">Winnie Pooh</button>

Примечание: {{hero.name}} имя будет заменено значением из компоненты.

Таким образом мы видем что при нажатии на элемент <child-component>, мы на самом деле будем кликать на <button (click)="selectHero()> вызывая selectHero() метод компоненты, который в свою очередь будет осуществлять вызов события методом emit (представителя класса EventEmitter о которых мы поговорим далее).

IgorKulishov commented 5 years ago
  1. EventEmitter это класс относящийся к RXJS библиотеке (Reactive library) мы будем подробно это проходить т.к. это активно используется в Angular. Поскольку мы это не проходили, то мне будет немного сложно объяснить. Скажу что это относится к библиотеке RXJS и это не совсем одно и тоже если сравнивать со стандартными HTML DOM javascript events. Думаю тут пока надо будет только запомнить что для взаимодействия дочерней компоненты с родительской мы применяем EventEmitter. Последовательность цепочки взаимодействия такая: дочерняя компонента посылает событие с объектом, сторой, номером или boolean при помощи метода emit класса EventEmitter родительской компоненте. Родительская компоненты "слушает" событие и при получении события активирует метод определенный в аттрибутах родительской компоненты (п. 2.C.):
    <child-component [hero]="hero"  (selectedHero)="onSelectHero($event)"></child-component>

Вначале будет тяжеловато. Но думаю надо просто запомнить применение (не разбираясь как это работает) и потренироваться / поупражняться с Output пока это будет более менее привычно.

Тем временем дай знать когда можно будет переключиться на Reactive library. Думаю что это должно быть и в видео уроке (посмотрю позже). Эта тема встречается в service (сервисах) и этот принцип используется во-всех http REST calls (GET, POST, PUT, DELETE) там применяются названия Observables и subscribers . На Reactive можно переключиться всегда - не надо ждать завершения предыдущей главы. Не прощаюсь - удачи тебе Бро!