SPA는 서버 측 렌더링 된 웹 사이트에 대한 대립으로 유행이되었습니다. 항상 장단점이 있지만 스파는 그러한 접근 방식없이 복제하기 어려운 원활한 사용자 경험을 만들 수 있습니다. 이는 Web Applications가 전통적으로 데스크탑 응용 프로그램에 의해 점유 된 영토로의 벤처의 일부입니다. 웹 애플리케이션은 일반적으로 데스크탑 앱과 비교할 때 느리게 부진한 것으로 비판하지만, 웹 기술 (특히 Nodejs 및 Google의 V8 엔진 및 Angular 및 Reactjs와 같은 프레임 워크)뿐만 아니라 전례없는 컴퓨팅 파워에 대한 주류 액세스가 크게 진행되는 것으로 비판됩니다. 예전보다 문제가 적습니다.
SPAS 기능은 클라이언트에 단일 HTML 페이지를로드 한 다음 사용자가 어디에서나 클릭 할 때마다 서버에서 업데이트 된 HTML 페이지를 검색하는 것과는 대조적으로 내용 (및 DOM)을 동적으로 업데이트하여 기능합니다.
NodeJS
및 npm
설치하십시오.TypeScript
설치하십시오.npm install -g @angular/cli
ng new my-project
cd my-project && ng serve
사용하여 로컬로 앱을 제공하십시오.localhost:4200
방문 할 수 있습니다. my-project/src/app/app.component.ts
열면 다음과 같은 것을 맞이해야합니다.
/** app.component.ts */
import { Component } from '@angular/core' ; // #1
@ Component ( { // #2
selector : 'app-root' , // #3
templateUrl : './app.component.html' , // #4
styleUrls : [ './app.component.css' ] // #5
} )
export class AppComponent {
title = 'app' ; // #6
}
이것을 조금 분류합시다.
node_modules
폴더에있는 @angular
모듈에서 Component
인터페이스를 가져옵니다.@Component
데코레이터는 클래스를 각도 구성 요소로 표시합니다. 데코레이터는 옵션 객체로 매개 변수화되며, 여기서 몇 가지 매개 변수 만 사용합니다.selector
매개 변수는 해당 구성 요소의 HTML 태그가 무엇인지 정의합니다. 예를 들어, <app-root> … </app-root>
사용하여 HTML에 주입됩니다.templateUrl
매개 변수는 구성 요소의 뷰 부분 역할을하는 HTML 파일을 가리키는 문자열 인수를 취합니다. 파일을 가리키는 대신 template
매개 변수를 사용하여 HTML을 직접 쓸 수도 있습니다. 보기 부분이 단순히 한 줄이 아닌 한 일반적으로 권장되지 않습니다.styleUrls
매개 변수는 문자열 목록을 가져옵니다. 여기서 각 문자열은 CSS 파일의 경로입니다.title
app.component.html
에서 참조 할 수 있습니다. app.component.html
로 이동하십시오. 이것은 응용 프로그램의 입장점이며 편집 해야하는 최고 수준의 HTML입니다. 이 맥락에서 모든 것이 렌더링됩니다.
이제이 파일의 내용을 삭제하고 다음과 같이 바꿉니다.
< div class =" container " >
< h1 > Live football scores </ h1 >
< div class =" score-card-list " >
< div class =" score-card " >
< span > Team 1 </ span >
< span > 0 : 0 </ span >
< span > Team 2 </ span >
</ div >
</ div >
</ div >
웹 브라우저로 돌아 가면 페이지가 자동으로 업데이트되었음을 알 수 있습니다. 엄청난.
시각적 으로이 단계에서 실망했을 것입니다. 그러나 그것은 진행중인 작업입니다.
Angular Materials는 Angular Applications에 사용하기 쉬운 재료 설계 구성 요소를 제공하기 위해 Google의 팀이 관리하는 라이브러리입니다. 이러한 구성 요소의 스타일은 Heart의 콘텐츠로 조정할 수 있지만 최소한의 노력으로 프로토 타입 앱의 모양과 느낌을 쉽게 업그레이드하는 방법을 제공합니다.
npm install --save @angular/material @angular/cdk @angular/animations
사용하여 필요한 라이브러리를 설치하겠습니다. 필요한 파일을 node_modules
폴더로 다운로드하고 packages.json
파일을 적절하게 업데이트합니다.
또한 관련 구성 요소를로드하려면 Angular에게 알려야합니다. 이것이 어떻게 작동하는지에 대한 인터넷 검색을 수행해야하지만 (이것은 101 덕트 테이프 종류의 자습서입니다), 기본적으로 필요한 모듈을 포함하려면 app.modules.ts
파일을 수정하면됩니다.
먼저 다음과 같은 애니메이션을 추가하십시오.
import { BrowserAnimationsModule } from '@angular/platform-browser/animations' ;
@ NgModule ( {
...
imports : [ BrowserAnimationsModule ] ,
...
} )
그런 다음 필요한 모듈을 추가하십시오.
import { MatButtonModule , MatCardModule } from '@angular/material' ;
@ NgModule ( {
...
imports : [ MatButtonModule , MatCardModule ] ,
...
} )
앱에서 사용할 구성 요소를 가져와야합니다. 전체 라이브러리를 포함하지 않는 이유는 webpack
트리 흔들림을 수행하는 데 도움이되는 것입니다. 기본적으로 모든 코드를 몇 개의 .js
미니어링 된 파일로 번들링 할 때 사용하지 않은 코드를 남기는 것이 기본적으로 수반됩니다.
이 작업이 완료되면 사전 정의 된 구성 요소가 많은 구성 요소에 액세스 할 수 있으며 필요에 따라 간단히 가져올 수 있습니다. 또한 사전 제작 된 테마는 사용하기 쉽다는 점도 주목할 가치가 있습니다.
각도에서 구성 요소는 모듈 식입니다. 각 구성 요소에는 자체 CSS 파일이 있으며 해당 특정보기에만 적용됩니다. 한 가지 예외는 src
디렉토리에있는 styles.css
파일이 전 세계적으로 적용됩니다.
스타일링은이 튜토리얼의 초점이 아니므로 가능한 한 앞으로도 피하려고 노력할 것입니다. 우리가 만드는 것에 대해 약간 더 나은 느낌을주기 위해서는 styles.css
파일에 복사하여 붙여 넣을 간단한 CSS가 있습니다 (향후 참조를 위해 적절한 구성 요소의 CSS 파일에 관련 비트를 추가하는 것이 좋습니다).
// Outer wrapper div
. container {
text-align : center;
}
// Wrapper for the score cards
. score-card-list {
display : flex;
flex-direction : column;
align-items : center;
}
// Each score card
. score-card {
width : 550 px ;
display : flex !important ;
}
// Home team score
. home {
flex : 1 ;
text-align : right;
}
// Away team score
. away {
flex : 1 ;
text-align : left;
}
// Score section of score card
. score {
width : 100 px ;
}
또한 클래스를 포함하도록 HTML을 업데이트하십시오.
...
< mat-card class =" score-card " >
< span class =" home " > Team 1 </ span >
< span class =" score " > 0 : 0 </ span >
< span class =" away " > Team 2 </ span >
</ mat-card >
...
flex
에 대해 혼란 스러우면 Flexbox Froggy를 확인하는 것이 좋습니다 .
Angular와 같은 프레임 워크를 사용하는 것 중 하나는 HTML에서 일부 프로그래밍 논리를 직접 구현할 수 있다는 것입니다. 우리의 경우, 루프가 생명을 훨씬 쉽게 만들어 줄 것입니다.
다음을 시도하십시오.
...
< mat-card class =" score-card " *ngFor =" let team of ['Arsenal', 'Liverpool', 'Tottenham']; let i=index " >
< span class =" home " > {{ team }} </ span >
< span class =" score " > 0 : 0 </ span >
< span class =" away " > Team {{ i+1 }} </ span >
</ mat-card >
...
이것은 다양한 새로운 개념을 소개하며 다음과 같은 것을 생산해야합니다.
주목할만한 개념 :
{{ 'Some text = ' + a_number }}
서비스는 구성 요소에서 데이터 액세스를 추상화하기 위해 사용됩니다. 이를 통해 구성 요소가 린 상태를 유지하고 뷰를 지원하는 데 집중할 수 있습니다. 이러한 책임 분리를 유지함으로써 단위 테스트 및 코드 유지 보수가 단순화됩니다.
CLI를 사용하여 서비스를 생성하려면 ng generate service football-data
(또는 제 시간에 짧은 사람들을위한 ng gs football-data
)를 사용할 수 있습니다. project-dir/src/app
디렉토리에서 football-data.service.ts
및 football-data.service.spec.ts
에서 두 개의 새 파일이 생성됩니다. 이는 테스트 파일이 .spec.ts
확장을받는 각도 규칙을 따릅니다. 테스트는 유용하고 중요하지만이 튜토리얼의 즉각적인 범위를 벗어나서 순간을 무시할 수 있습니다 (죄송합니다, @Cornel).
football-data.service.ts
에 다음 줄을 추가하십시오.
import { Injectable } from '@angular/core' ;
import { HttpHeaders } from '@angular/common/http' ;
@ Injectable ( ) // Designate this class as an injectable service
export class FootballDataService {
// Token for accessing data on football-data.org (see: https://www.football-data.org/client/register)
HEADERS = new HttpHeaders ( { 'X-Auth-Token' : 'dc25ff8a05123411sadgvde5bb16lklnmc7' } ) ;
// Convenience constant
COMPETITION_URL = 'http://api.football-data.org/v1/competitions/' ;
// ID for the Premier League
PL_ID = 445 ;
constructor ( ) { }
}
서비스는 @Injectable
과 주석이 달리며, 이는 컴파일러에게 서비스 인스턴스가 구성 요소에 주입 될 수 있음을 알려줍니다. 또한 각 서비스에 대한 제공자를 지정해야합니다. 제공자는 지정된 레벨에서 싱글 톤을 효과적으로 제공합니다.
예를 들어, app.module.ts
의 제공 업체 배열에 서비스를 추가 할 수 있으며, 이로 인해 전체 앱 전체에 서비스의 싱글 톤 인스턴스가 노출됩니다. 그렇지 않으면 구성 요소의 제공 업체 목록에 추가 할 수 있으므로 해당 구성 요소와 해당 구성 요소에 싱글 톤 인스턴스를 사용할 수 있습니다.
경고 : 앱이 커지면 서비스 간의 원형 종속성을 쉽게 만들 수 있습니다. 이것을 염두에 두십시오. Cannot resolve all parameters for MyDataService(?)
오류 메시지가 발생하면 원형 종속성 문제와 관련이있을 수 있습니다.
우리는 Football-Data.org에서 환상적인 API를 자유롭게 사용할 수 있습니다. 자신의 API 키를 가져와야하지만 쉽게 수행 할 수 있습니다. 사이트의 지침을 따르십시오. 더 심층적 인 문서가 있지만 여기에 나열된 작은 예에서 필요한 것의 99%를 볼 수 있습니다.
이 예에서, 우리가 정말로하고 싶은 것은 현재 라운드의 모든 게임에 대한 게임 정보를 검색하는 것입니다 (일명 "게임 주"또는 "매치 데이"). /v1/competitions/{id}/fixtures
endpoint는이 정보를 반환하지만 현재 시즌의 모든 라운드에 대해서는이 정보를 반환합니다. 단일 라운드에 대한 정보를 얻으려면 matchday
매개 변수 (예 : /v1/competitions/{id}/fixtures?matchday=14
설정해야합니다.
현재 매치 데이를 얻으려면 리그 테이블이 기본적으로 현재 경기 일로 돌아 오기 때문에 리그 테이블을 요청할 수 있습니다.
먼저 Angular의 HTTP 기능을 사용하기 위해 HttpClient
서비스를 FootballDataService
에 주입해야합니다.
import { HttpClient , HttpHeaders } from '@angular/common/http' ;
...
constructor ( private http : HttpClient ) { }
. . .
중요 : Angular 서비스 또는 구성 요소의 생성자에 개인 변수를 특정 TypeScript 유형 선언과 함께 Angular의 Black Magic에 대한 충분한 정보입니다. 컴파일러는 이제이 서비스에 적절한 인스턴스를 주입하므로 액세스 할 수 있습니다.
서버에서 리그 테이블 (및 현재 매치 데이)을 검색하는 기능을 추가하겠습니다.
...
getTable ( ) {
return this . http . get ( this . COMPETITION_URL + this . PL_ID + '/leagueTable' ,
{ headers : this . HEADERS } ) ;
}
...
TypeScript는 이에 도움이되지만 Angular의 http.get
메소드의 메소드 서명은 다음과 같이 보입니다.
/**
* Construct a GET request which interprets the body as JSON and returns it.
*
* @return an `Observable` of the body as an `Object`.
*/
get ( url : string , options ?: {
headers ?: HttpHeaders | {
[ header : string ] : string | string [ ] ;
} ;
observe?: 'body' ;
params?: HttpParams | {
[ param : string ] : string | string [ ] ;
} ;
reportProgress?: boolean ;
responseType?: 'json' ;
withCredentials?: boolean ;
} ) : Observable < Object > ;
물음표는 매개 변수 headers
, observe
, params
, reportProgress
, responseType
및 withCredentials
가 options
의 선택적 개체의 일부로 선택 사항임을 나타냅니다. 우리는 url
및 options.headers
에 대한 값 만 전달할 것입니다.
우리가 방금 생성 한 getTable()
함수가 무엇인지 궁금 할 것입니다. 글쎄, 그것은 Observable
스트림을 반환합니다. Luuk Gruijs는 "시간이 지남에 따라 여러 값의 게으른 컬렉션"이라고 말한 것처럼 Observable
S는 본질적으로 본질적으로 적용됩니다. 미쳤지 만 실제로는 매우 간단합니다.
요컨대, Observable
스트림은 구독 될 때까지 "차가운"것으로 간주됩니다. 즉, 변수는 출력이 사용되면 게으르게로드됩니다. 스트림이 "핫"되면 값이 변경 될 때마다 모든 가입자가 업데이트됩니다. JavaScript에서 비동기 상황을 처리하기위한 Promise
사용하는 대안입니다.
이 경우, GET
요청은 REST 인터페이스가 통화 당 단일 값 만 반환되므로 Observable
변수가 구독되면 발생합니다.
우리는 TypeScript에서 정적 타이핑의 전력을 사용하여 더 명시 적으로 만들 수 있습니다.
...
import { Observable } from 'rxjs/Observable' ;
...
getTable ( ) : Observable < any > {
return this . http . get ( this . COMPETITION_URL + this . PL_ID + '/leagueTable' ,
{ headers : this . HEADERS } ) ;
}
...
실제로, 축구 -Data.org 문서는 나머지 통화에서 기대할 내용을 정확하게 알려 주므로 src/app/models/leagueTable.ts
에서 한 걸음 더 나아가 객체를 모델링 할 수 있습니다.
import { Team } from './team' ;
export class LeagueTable {
leagueCaption : string ;
matchday : number ;
standing : Team [ ] ;
}
그리고 src/app/models/team.ts
:
export class Team {
teamName : string ;
crestURI : string ;
position : number ;
points : number ;
playedGames : number ;
home : {
goals : number ;
goalsAgainst : number ;
wins : number ;
draws : number ;
losses : number ;
} ;
away : {
goals : number ;
goalsAgainst : number ;
wins : number ;
draws : number ;
losses : number ;
} ;
draws : number ;
goalDifference : number ;
goals : number ;
goalsAgainst : number ;
losses : number ;
wins : number ;
}
이를 통해 football-data.service.ts
다음과 같이 업데이트 할 수 있습니다.
import 'rxjs/add/operator/map' ;
import { LeagueTable } from './models/leagueTable' ;
...
getTable ( ) : Observable < LeagueTable > {
return this . http . get ( this . COMPETITION_URL + this . PL_ID + '/leagueTable' ,
{ headers : this . HEADERS } )
. map ( res => res as LeagueTable ) ;
}
...
이것은 IDE가 우리를 인도 할 수 있으므로 복잡한 물체로 작업하는 동안 최신 상태를 유지하는 데 필요한 정신 모델을 최소화함으로써 우리의 정신을 유지하는 데 도움이 될 것입니다.
참고 : as
키워드는 단순히 TypeScript에게 객체의 유형에 대해 우리를 신뢰하도록 지시합니다. 위험하지만 가장 흥미로운 것들처럼 유용합니다.
좋아, src/app/app.component.ts
로 다시 탐색하고 다음 줄을 추가하여 FootballDataService
구성 요소에 주입하십시오.
import { FootballDataService } from './football-data.service' ;
...
export class AppComponent {
title = 'app' ;
constructor ( private footballData : FootballDataService ) { }
}
이제 구성 요소에 ngOnInit
방법을 추가합니다. 이것은 구성 요소의 모든 데이터 바운드 특성이 초기화 된 후에 발사되는 Angular가 제공하는 표준 수명주기 후크입니다. 기본적으로 객체의 초기화시 발사되지만 구성 요소에 대한 모든 입력 및 출력이 등록되기 전에 constructor
방법보다 약간 늦습니다.
일반적인 규칙은 생성자가 아닌이 특수 ngOnInit
방법에서 초기화에서 호출하려는 코드를 항상 배치하는 것입니다. SO와 같은 구성 요소에 추가하십시오.
import { Component , OnInit } from '@angular/core' ;
...
export class AppComponent implements OnInit {
...
constructor ( private footballData : FootballDataService ) { }
ngOnInit ( ) {
// Code you want to invoke on initialisation goes here
}
...
우리의 경우, 우리는 리그 테이블을로드하려고하므로 다음과 같은 것을 추가 할 수 있습니다.
...
ngOnInit ( ) {
// Load league table from REST service
this . footballData . getTable ( )
. subscribe (
data => console . log ( data ) ,
error => console . log ( error )
) ;
}
...
웹 브라우저에서 콘솔을 열면 다음과 같은 것을 볼 수 있습니다.
엄청난. 우리는 이제 우리가 앞으로 무언가를 할 수있는 멋진 데이터를 많이 가지고 있지만 (클럽 크레스트 이미지와 직접 연결), 지금은 현재 매치 데이에 관심이 있습니다.
이제 현재 고정물 라운드에 대한 정보를 얻기 위해 데이터 서비스에 다른 기능을 추가하겠습니다.
...
import { GameWeek } from './models/gameWeek' ;
...
getFixtures ( matchDay : number ) : Observable < GameWeek > {
return this . http . get ( this . COMPETITION_URL + this . PL_ID + '/fixtures?matchday=' + matchDay , { headers : this . HEADERS } )
. map ( res => res as GameWeek ) ;
}
...
GameWeek
및 Fixture
다음과 같이 정의됩니다.
// src/app/models/gameWeek.ts
import { Fixture } from './fixture'
export class GameWeek {
count : number ;
fixtures : Fixture [ ] ;
}
// src/app/models/fixture.ts
export class Fixture {
awayTeamName : string ;
date : string ;
homeTeamName : string ;
matchday : number ;
result : {
goalsAwayTeam : number ;
goalsHomeTeam : number ;
halfTime : {
goalsAwayTeam : number ;
goalsHomeTeam : number ;
}
} ;
status : 'SCHEDULED' | 'TIMED' | 'POSTPONED' | 'IN_PLAY' | 'CANCELED' | 'FINISHED' ;
_links : {
awayTeam : { href : string ; } ;
competition : { href : string ; } ;
homeTeam : { href : string ; } ;
self : { href : string ; } ;
} ;
}
새로 얻은 매치 데이 지식을 통해 현재 비품 라운드에 대한 정보를 REST 서버에 요청할 수 있습니다. 그러나 두 번째를 수행하기 전에 첫 번째 휴식 전화가 먼저 완료 될 때까지 기다려야합니다. 일부 리팩토링은 콜백에서 상당히 쉽게 할 수 있음을 의미합니다.
import { Component , OnInit } from '@angular/core' ;
import { FootballDataService } from './football-data.service' ;
import { LeagueTable } from './models/leagueTable' ;
@ Component ( {
selector : 'app-root' ,
templateUrl : './app.component.html' ,
styleUrls : [ './app.component.css' ] ,
providers : [ FootballDataService ]
} )
export class AppComponent implements OnInit {
title = 'app' ;
table : LeagueTable ;
gameweek : GameWeek ;
constructor ( private footballData : FootballDataService ) { }
ngOnInit ( ) {
this . getTable ( ) ;
}
getTable ( ) {
this . footballData . getTable ( )
. subscribe (
data => {
this . table = data ; // Note that we store the data locally
this . getFixtures ( data . matchday ) ; // Call this function only after receiving data from the server
} ,
error => console . log ( error )
) ;
}
getFixtures ( matchDay : number ) {
this . footballData . getFixtures ( matchDay )
. subscribe (
data => this . gameweek = data , // Again, save locally
error => console . log ( error )
) ;
}
}
이제 우리는 어딘가에 도착합니다!
데이터를 TypeScript 구성 요소에서 멤버 변수로 설정 했으므로 관련 HTML에서 직접 액세스 할 수 있습니다. 실제로 Microsoft의 Open-Source 편집기 인 Visual Studio Code를 사용하는 경우 Angular Language Service 플러그인을 추가하여 HTML에서 JavaScript 코드 완료를 얻을 수 있습니다! 놀라운. 그리고 그것은 각도 팀에 의해 유지됩니다.
이전의 더미 데이터를 교체합시다.
< div class =" container " >
< h1 > Live football scores </ h1 >
< div class =" score-card-list " >
< mat-card class =" score-card " *ngFor =" let fixture of gameweek.fixtures " >
< span class =" home " > {{ fixture.homeTeamName }} </ span >
< span class =" score " > {{ fixture.result.goalsHomeTeam }} : {{ fixture.result.goalsAwayTeam }} </ span >
< span class =" away " > {{ fixture.awayTeamName }} </ span >
</ mat-card >
</ div >
</ div >
gameweek?.fixtures
구문 : the ?
기호는 if (gameweek != null) { return gameweek.fixtures } else { return null }
에 대한 짧은 손으로 작용하며, 비동기식 휴식 전화로만 채워질 변수에 액세스 할 때 믿을 수 없을 정도로 유용합니다.
ET Voila!
이 다음 부분은 엄격히 필요하지 않지만, 중요한 일을하는 중요한 각도 방법을 보여 주며, 우리가 그것을 앞으로 가져 가기로 결정한 경우 코드 모듈화되고 포함 가능하게 유지하는 데 도움이 될 것입니다 (NativeScript를 각도 및 타입 스크립트가있는 기본 모바일 앱).
우리는 고정 점수 카드를 자체 구성 요소로 옮길 것입니다. CLI : ng generate component score-card
(또는 ng gc score-card
)의 도움으로 시작하십시오. src/app/score-card
에서 .ts
, .html
및 .css
파일이 생성됩니다.
친숙한 데코레이터가 인사 할 score-card.component.ts
열어보세요 :
...
@ Component ( {
selector : 'app-score-card' , // Note this!
templateUrl : './score-card.component.html' ,
styleUrls : [ './score-card.component.css' ]
} )
...
selector
필드에 유의하십시오-구성 요소에 액세스하는 방법을 알려줍니다 (이 경우 <app-score-card></app-score-card>
태그를 사용하여).
app.component.html
에서 고기를 score-card.component.html
로 이동하여 코드를 리팩터링하십시오.
<!-- app.component.html -->
< div class =" container " >
< h1 > Live football scores </ h1 >
< div class =" score-card-list " >
< app-score-card *ngFor =" let fixture of gameweek?.fixtures " [fixture] =" fixture " > </ app-score-card >
</ div >
</ div >
<!-- score-card.component.html -->
< mat-card class =" score-card " >
< span class =" home " > {{ fixture.homeTeamName }} </ span >
< span class =" score " >
{{ fixture.result.goalsHomeTeam }} : {{ fixture.result.goalsAwayTeam }}
</ span >
< span class =" away " > {{ fixture.awayTeamName }} </ span >
</ mat-card >
<app-score-card>
태그 내부의 [fixture]="fixture"
비트를 참고하십시오. 이것이 우리가 구성 요소간에 정보를 전달하는 방법입니다.
각도 구문에서 [...]
입력을 나타내고, (…)
는 출력을 나타내고, [(…)]
양방향 결합을 나타냅니다. [(…)]
"바나나 박스 구문"이라고도하며 [(ngModel)]="someVariable"
의 형태로 자주 발생합니다. 이는 변수 값과 DOM 객체의 값 사이의 양방향 결합을 의미합니다. 이것은 Angular 사용의 핵심 부분입니다.
예를 들어, input
태그의 값을 화면에 표시되는 변수에 직접 매핑 할 수 있으며 input
요소의 값이 변경 될 때마다 DOM이 자동으로 업데이트됩니다.
< p >
What is your name?
< input type =" text " [(ngModel)] =" name " />
</ p >
< p >
Your name: {{ name }}
</ p >
여기에서 예제 플러커를 확인할 수 있습니다.
축구로 돌아 가기 : 구성 요소에 입력 값을 받으려면 다음과 같이 score-card.component.ts
업데이트해야합니다.
import { Component , Input } from '@angular/core' ;
import { Fixture } from '../models/fixture' ;
@ Component ( {
selector : 'app-score-card' ,
templateUrl : './score-card.component.html' ,
styleUrls : [ './score-card.component.css' ]
} )
export class ScoreCardComponent {
@ Input ( ) fixture : Fixture ; // Note the decorator
constructor ( ) { }
}
구성 요소간에 데이터를 전달하는 두 가지 명백한 방법이 있습니다 : @Input
/ @Output
사용 및 서비스 사용.
@Input()
첫 번째 방법은 부모와 자녀 사이의 데이터를 전달하는 데 유용하지만 데이터가 중첩 레이어를 통해 이동 해야하는 경우 지루할 수 있습니다. @Input
데코레이터를 사용하여 데이터를 하위 구성 요소로 전달할 수 있습니다. 이 입력 변수는 객체 인 경우 참조별로 전달되거나 원시인 경우 값으로 전달됩니다.
// someComponent.ts
// ...
import { Input } from '@angular/core'
// ...
export class SomeComponent {
// @Input() variables get set after the `constructor(...)`
// method, but before `ngOnInit()` fires
@ Input ( ) aNumber : number ; // This gets set via parent HTML
// ...
}
<!-- someComponentParent.html -->
< h1 >
I am a parent where SomeComponent gets rendered
</ h1 >
<!-- Pass a value to the aNumber variable -->
< some-component [aNumber] =" 48 " > </ some-component >
@Output()
@Output()
데코레이터를 사용하여 데이터를 어린이에서 부모 구성 요소로 방출 할 수도 있습니다. 이것은 방향 적 바인딩이 아니라 사전 정의 된 시간에 발사되는 이벤트 이미 터입니다. 어린이의 값이 변경되면 전형적인 사용 사례는 부모에게 알리는 것입니다.
// someComponent.ts
// ...
import { Input , Output , EventEmitter } from '@angular/core'
// ...
export class SomeComponent {
@ Input ( ) aNumber : number ;
// Emits an event (of type `number`) to the parent
@ Output ( ) numberChanged : EventEmitter < number > = new EventEmitter < number > ( ) ;
// ...
// Event emitters need to be triggered manually
// Any object can be emitted
emitValueChanged ( ) : void {
this . numberChanged . emit ( this . aNumber ) ;
}
}
<!-- someComponentParent.html -->
< h1 >
I am a parent where SomeComponent gets rendered
</ h1 >
<!-- Pass a value to the aNumber variable -->
< some-component [aNumber] =" 48 " (valueChanged) =" aNumberChanged($event) " > </ some-component >
// someComponentParent.ts
export class SomeParentComponent {
// ...
aNumberChanged ( updatedNumber : number ) : void {
console . log ( `aNumber changed to ${ updatedNumber } ` ) ;
}
// ...
}
서비스 사용
서비스를 사용하여 구성 요소간에 데이터를 전달하는 방법에는 여러 가지가 있습니다. 세부 사항은이 튜토리얼의 범위를 벗어나지 만 비교적 복잡한 응용 프로그램에서 필요할 수 있기 때문에 그러한 기술의 존재를 주목할 가치가 있습니다.
일반적인 패턴은 서비스에서 Observable
스트림을 정의하는 것인데, 이는 구성 요소가 메시지를 푸시하거나 구독하여 새 메시지를 통지 할 수 있습니다. 이것은 사실상 이벤트 버스입니다.
일반적으로 청취자가 적용 가능한 사람을 식별 할 수 있도록 메시지를 입력해야합니다. 다소 경박 한 예로서,이 서비스는 PersonNameChangedEvent
PersonComponent
을 방출 할 수있는 반면 LandingPageComponent
이 사건을 완전히 무시하기로 선택할 수 있습니다.
Angular는 응용 프로그램을 구축하기 위해 모 놀리 식적이고 고도로 의견이 많은 프레임 워크를 제공합니다. 이는 구조의 이점을 제공합니다. 프레임 워크의 의견이 많은 특성은 사용자가 확장 가능한 앱을 Get -Go에서 설계하는 데 도움이되며 많은 복잡성이 개발자로부터 숨겨져 있습니다. 반면에, Angular (및 Typecript, 그 문제에 대해) 사용하면 작은 응용 프로그램을 구축하는 경우 속도가 느려질 수있는 많은 보일러 플레이트 코드가 소개되므로 Angular로 이동하기 전에 앱이 어디로 가는지 고려할 가치가 있습니다.
그러나 Angular CLI는 먼 길을 왔으며, 무거운 리프팅의 양을 고려할 때 가까운 시일 내에 거의 모든 프로젝트에 Angular를 사용할 것입니다.