Angular 6 튜토리얼: 새로운 기능과 새로운 기능

게시 됨: 2022-03-11

Angular 6이 나왔습니다! 가장 눈에 띄는 변경 사항은 CLI와 서비스가 주입되는 방식입니다. 첫 번째 Angular 6 앱 또는 Angular/Firebase 앱을 작성하려는 경우 이 자습서에서 초기 설정의 기본 단계를 살펴보고 작은 일기 앱을 만듭니다.

Angular 6: 기본 사항

이전에 Angular를 사용한 적이 없다면 Angular에 대한 간단한 설명과 작동 방식을 알려 드리겠습니다.

Angular는 데스크톱 및 모바일용 단일 페이지 애플리케이션(SPA) 구축을 지원하도록 설계된 JavaScript 프레임워크입니다.

프레임워크에는 탐색, 권한 부여, 양식 및 보고와 같은 웹 앱에 대한 가장 일반적인 시나리오 중 일부를 쉽게 구현할 수 있는 완전한 지시문 및 모듈 제품군이 포함되어 있습니다. 또한 Jasmine 프레임워크를 사용하여 테스트를 추가하고 Karma 또는 Protractor 테스트 러너를 사용하여 테스트를 실행하는 데 필요한 모든 패키지가 함께 제공됩니다.

Angular 아키텍처는 구성 요소, 템플릿, 지시문 및 서비스를 기반으로 합니다. 뷰를 구성 요소 코드와 연결하기 위한 양방향 데이터 바인딩뿐만 아니라 서비스에 대한 기본 제공 종속성 주입 메커니즘을 제공합니다.

Angular는 JS의 유형화된 상위 집합인 TypeScript를 사용하며 특히 유형화된 언어 배경에서 온 경우 몇 가지 작업을 더 쉽게 만듭니다.

Angular 6: 새로운 기능

Angular 6의 새로운 기능에 대한 간략한 요약:

  • 프레임워크 패키지( @angular/core , @angular/common , @angular/compiler 등), CLI, Material 및 CDK의 주요 버전 번호를 동기화하는 정책입니다. 이것은 앞으로 상호 호환성을 더 명확하게 하는 데 도움이 될 것입니다. 주요 패키지가 서로 호환되는지 여부를 버전 번호를 한 눈에 빠르게 알 수 있습니다.
  • 새로운 ng CLI 명령:
    • ng update 를 통해 패키지 버전을 현명하게 업그레이드하고 종속성 버전을 업데이트하고 동기화 상태를 유지합니다. (예: ng update @angular/core 를 실행할 때 모든 프레임워크와 RxJS가 업데이트됩니다.) 패키지에 포함된 경우 회로도 도 실행됩니다. (새 버전에 코드 변경이 필요한 주요 변경 사항이 포함된 경우 회로도에서 코드를 업데이트합니다.)
    • ng add 하기 위해 추가(해당되는 경우 스크립트 실행)
  • 서비스는 이제 서비스를 참조하는 모듈 대신 서비스를 제공할 모듈을 참조합니다.

이 마지막 변경이 의미하는 바에 대한 예로서 코드가 다음과 같았습니다.

 @NgModule({ // ... providers: [MyService] })

...Angular 6의 이러한 특정 변경으로 인해 다음과 같이 보일 것입니다.

 @Injectabe({ providedIn: 'root', })

이를 트리 흔들 수 있는 공급자 라고 하며 컴파일러가 참조되지 않은 서비스를 제거하여 더 작은 크기의 번들을 만들 수 있습니다.

앵귤러 6 CLI

ng 명령줄 인터페이스는 Angular의 매우 중요한 부분이며 앱을 코딩할 때 더 빠르게 이동할 수 있습니다.

CLI를 사용하면 초기 앱 설정을 매우 쉽게 스캐폴딩하고 새 구성 요소, 지시문 등을 생성하고 로컬 환경에서 앱을 빌드 및 실행할 수 있습니다.

Angular 6 프로젝트 만들기

알겠습니다. 충분한 이야기입니다. 손을 더럽히고 코딩을 시작합시다.

시작하려면 컴퓨터에 Node.js와 npm이 설치되어 있어야 합니다.

이제 CLI를 설치해 보겠습니다.

 npm install -g @angular/cli

-g 스위치로 인해 ng CLI 명령이 전역으로 설치됩니다.

일단 가지고 있으면 ng new 를 사용하여 앱의 초기 스캐폴드를 얻을 수 있습니다.

 ng new my-memories --style=scss

그러면 my-memories 폴더가 생성되고, 초기 설정을 시작할 준비를 하는 데 필요한 모든 파일이 생성되고, 필요한 모든 패키지가 설치됩니다. --style=scss 스위치는 선택 사항이며 SCSS 파일을 CSS로 컴파일하도록 컴파일러를 설정합니다. 이는 나중에 필요합니다.

설치가 완료되면 cd my-memories 하고 ng serve 를 실행할 수 있습니다. 그러면 빌드 프로세스와 http://localhost:4200 에서 앱을 제공하는 로컬 웹 서버가 시작됩니다.

스캐폴딩 직후의 Angular 6 앱

배후에서 일어나고 있는 일은 CLI가 모든 .ts (TypeScript 파일)를 바닐라 JS로 변환하고, 패키지 폴더 node_modules 에서 필요한 모든 종속성을 수집하고, 결과를 로컬 웹 서버를 통해 제공되는 파일 세트로 출력한다는 것입니다. 포트 4200에서 실행됩니다.

프로젝트 파일

Angular의 프로젝트 폴더 구조에 익숙하지 않다면 가장 중요한 것은 앱과 관련된 모든 코드가 src 폴더 안에 들어간다는 것입니다. 일반적으로 앱 아키텍처(예: 사용자, 장바구니, 제품)에 따라 해당 폴더에 모든 모듈과 지시문을 생성합니다.

Angular 6 프로젝트 폴더 구조

초기 설정

자, 지금까지 앱에 대한 초기 설정이 있습니다. 몇 가지 변경을 시작하겠습니다.

시작하기 전에 src 폴더를 조금 파헤쳐 보겠습니다. 초기 페이지는 index.html 입니다.

 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>MyMemories</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <body> <app-root></app-root> </body> </html>

여기에 몇 가지 기본 HTML과 <app-root> 태그가 있습니다. 이것은 Angular 구성 요소이며 Angular 6이 구성 요소 코드를 삽입합니다.

index.html 파일에 있는 것과 일치하는 선택기 app-root 가 있는 app/app.component.ts 파일을 찾습니다.

구성 요소는 데코레이팅된 TypeScript 클래스이며 이 경우 title 속성이 포함됩니다. @Component 데코레이터는 Angular에 클래스에 구성 요소 동작을 포함하도록 지시합니다. 선택기 외에도 렌더링할 HTML 파일과 사용할 스타일시트를 지정합니다.

 import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'app'; }

app.component.html 을 보면 {{title}} 보간 바인딩을 볼 수 있습니다. 여기에서 모든 매직 바인딩이 발생하고 Angular는 클래스 제목 속성의 값을 렌더링하고 변경될 때마다 업데이트합니다.

 <!--The content below is only a placeholder and can be replaced.--> <div> <h1> Welcome to {{ title }}! </h1> <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> </div> <h2>Here are some links to help you start: </h2> <ul> <li> <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2> </li> </ul>

계속해서 수업의 title'My Memories!' 로 업데이트합시다. .

 ... export class AppComponent { title = 'My Memories!'; } ...

컴파일러가 변경 사항을 처리하고 브라우저를 새로 고쳐 업데이트된 제목을 표시하는 것을 볼 수 있습니다.

이것은 Angular 6의 ng serve 파일 변경 사항을 감시하고 파일에 변경 사항이 도입될 때마다 렌더링한다는 것을 의미합니다.

코딩을 보다 친숙하게 만들고 변경할 때마다 전체 페이지 새로 고침을 피하기 위해 전체 새로 고침을 생성하는 대신 변경된 JS/CSS 청크만 업데이트하는 webpack HMR(핫 모듈 교체)을 활용할 수 있습니다. 변경 사항을 보여줍니다.

HMR 구성

먼저 환경을 설정해야 합니다.

다음 내용으로 src/environments/environment.hmr.ts 파일을 만듭니다.

 export const environment = { production: false, hmr: true };

src/environments/environment.prod.ts 를 업데이트하고 hmr: false 플래그를 환경에 추가합니다.

 export const environment = { production: true, hmr: false };

그런 다음 src/environments/environment.ts 를 업데이트하고 hmr: false 플래그를 환경에도 추가합니다.

 export const environment = { production: false, hmr: false };

다음으로 angular.json 파일에서 이 부분을 업데이트합니다.

 "projects": { "my-memories": { // ... "architect": { "build": { // ... "configurations": { "hmr":{ "fileReplacements":[ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.hmr.ts" } ] }, // ...

그리고 projectsmy-memoriesarchitectserveconfigurations 에서 :

 "projects": { "my-memories": { "architect": { // ... "serve": { // ... "configurations": { "hmr": { "browserTarget": "my-memories:build:hmr" }, // ...

이제 compilerOptions 옵션 아래에 다음을 추가하여 필요한 types (글쎄, 유형)을 포함하도록 tsconfig.app.json 을 업데이트하십시오.

 "compilerOptions": { // ... "types": [ "node" ]

다음으로 @angularclass/hmr 모듈을 개발 종속성으로 설치합니다.

 npm install --save-dev @angularclass/hmr

그런 다음 src/hmr.ts 파일을 만들어 구성합니다.

 import { NgModuleRef, ApplicationRef } from '@angular/core'; import { createNewHosts } from '@angularclass/hmr'; export const hmrBootstrap = (module: any, bootstrap: () => Promise<NgModuleRef<any>>) => { let ngModule: NgModuleRef<any>; module.hot.accept(); bootstrap().then(mod => ngModule = mod); module.hot.dispose(() => { const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef); const elements = appRef.components.map(c => c.location.nativeElement); const makeVisible = createNewHosts(elements); ngModule.destroy(); makeVisible(); }); };

다음으로 위의 기능을 사용하도록 src/main.ts 를 업데이트합니다.

 import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; import { hmrBootstrap } from './hmr'; if (environment.production) { enableProdMode(); } const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule); if (environment.hmr) { if (module[ 'hot' ]) { hmrBootstrap(module, bootstrap); } else { console.error('HMR is not enabled for webpack-dev-server!'); console.log('Are you using the --hmr flag for ng serve?'); } } else { bootstrap().catch(err => console.log(err)); }

여기서 우리가 하고 있는 것은 부트스트랩이 익명 함수를 호출하도록 하고 다음으로 environment.hmr 플래그가 참인지 여부를 묻는 것입니다. 그렇다면 핫 모듈 교체를 가능하게 하는 hmr.ts 에서 이전에 정의된 함수를 호출합니다. 그렇지 않으면 이전처럼 부트스트랩합니다.

이제 ng serve --hmr --configuration=hmr 을 실행할 때 hmr 구성을 호출하고 파일을 변경할 때 전체 새로 고침 없이 업데이트를 받습니다. 첫 번째 --hmr 은 webpack용이고 --configuration=hmr 은 Angular가 hmr 환경을 사용하기 위한 것입니다.

프로그레시브 웹 앱(PWA)

Angular 6 PWA 지원을 추가하고 앱에 대한 오프라인 로드를 활성화하기 위해 새로운 CLI 명령 중 하나인 ng add 를 사용할 수 있습니다.

 ng add @angular/[email protected]

이 튜토리얼을 작성할 때 최신 버전에서 오류가 발생했기 때문에 버전을 추가하고 있습니다. (그것 없이 시도하고 단순히 ng add @angular/pwa 를 사용하여 작동하는지 확인할 수 있습니다.)

좋습니다. 명령을 실행한 후 프로젝트에서 많은 변경 사항을 볼 수 있습니다. 가장 중요한 변경 사항은 다음과 같습니다.

  • angular.json 자산 파일의 manifest.json 에 대한 참조로 빌드 출력에 포함되고 "serviceWorker": true
  • 앱 실행에 필요한 모든 파일을 캐시하기 위한 초기 설정이 포함된 ngsw-config.json 파일
  • index.html 파일의 manifest.json 메타 태그
  • 앱에 대한 기본 구성이 포함된 manifest.json 파일 자체
  • 앱 모듈 ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) 의 서비스 워커 로드(서비스 워커는 프로덕션 환경에서만 활성화됩니다)

따라서 이것은 이제 사용자가 URL에 처음 액세스할 때 파일이 다운로드됨을 의미합니다. 그 후 사용자가 네트워크 서비스 없이 URL에 액세스하려고 하면 앱은 캐시된 파일을 가져와 계속 작동합니다.

Material Angular 6 UI 라이브러리 추가

지금까지 초기 설정이 완료되었으며 앱 빌드를 시작할 준비가 되었습니다. 이미 빌드된 구성 요소를 사용하려면 Angular 6 버전의 Material을 사용할 수 있습니다.

앱에 material 패키지를 설치하기 위해 다시 ng add 를 사용할 것입니다.

 ng add @angular/material

실행한 후 몇 가지 새로운 패키지가 추가되고 몇 가지 기본 스타일 구성이 표시됩니다.

  • index.html 에는 Roboto 글꼴 및 Material 아이콘이 포함됩니다.
  • BrowserAnimationsModuleAppModule 에 추가되었습니다.
  • angular.json 에는 인디고 핑크 테마가 이미 포함되어 있습니다.

미리 빌드된 Angular 6 테마 선택 표시

테마를 선택하려면 ng serve 를 다시 시작해야 하거나 미리 빌드된 다른 테마를 선택할 수 있습니다.

관련 항목: Angular Material을 사용하여 최신 웹 앱 구축

기본 레이아웃

초기 sidenav 레이아웃을 사용하려면 Material과 함께 제공되는 회로도를 사용합니다. 하지만 다른 레이아웃을 사용하고 싶다면 괜찮습니다.

(간단히 말하면 도식을 사용하면 프로젝트에 변환을 적용할 수 있습니다. 필요에 따라 파일을 생성, 수정 또는 삭제할 수 있습니다. 이 경우 앱의 sidenav 레이아웃을 스캐폴딩합니다.)

 ng generate @angular/material:material-nav --name=my-nav

그러면 시작할 준비가 된 최소 설정으로 sidenav 구성 요소가 생성됩니다. 대단하지 않아?

또한 app.module.ts 에 필요한 모든 모듈을 포함했습니다.

새로 생성된 "my-nav" Angular 6 구성 요소

SCSS를 사용하고 있으므로 my-nav.component.css 파일의 이름을 my-nav.component.scss -nav.component.scss로 변경하고 my- my-nav.component.ts 에서 새 이름을 사용하도록 해당 참조 styleUrls 을 업데이트해야 합니다.

이제 새 구성 요소를 사용하기 위해 app.component.html 로 이동하여 모든 초기 코드를 제거하고 다음 항목만 남겨둡니다.

 <app-my-nav></app-my-nav>

브라우저로 돌아가면 다음과 같이 표시됩니다.

왼쪽 상단 모서리에 메뉴가 있는 4개 창 레이아웃, 그 옆에 my-memories, 메뉴 아래에 번호가 매겨진 링크 3개. 네 번째 창은 비어 있습니다

원하는 두 가지 옵션만 갖도록 링크를 업데이트하겠습니다.

먼저 두 개의 새 구성 요소를 만들어 보겠습니다.

 ng gc AddMemory ng generate @angular/material:material-table --name=view-memories

(두 번째 것은 테이블을 생성하는 데 사용되는 재료 회로도입니다.)

다음으로 my-nav 에서 링크를 설정하고 콘텐츠 구성 요소를 표시하기 위해 <router-outlet> 을 포함하도록 업데이트합니다.

 <mat-sidenav-container class="sidenav-container"> <mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)"> <mat-toolbar color="primary">Menu</mat-toolbar> <mat-nav-list> <a mat-list-item [routerLink]="['/add-memory']">Add Memory</a> <a mat-list-item [routerLink]="['/view-memories']">View My Memories</a> </mat-nav-list> </mat-sidenav> <mat-sidenav-content> <mat-toolbar color="primary"> <button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" *ngIf="isHandset$ | async"> <mat-icon aria-label="Side nav toggle icon">menu</mat-icon> </button> <span>my-memories</span> </mat-toolbar> <router-outlet></router-outlet> </mat-sidenav-content> </mat-sidenav-container>

또한 app.component.html 에서 기본 <router-outlet> 만 갖도록 업데이트해야 합니다(즉, <my-nav> 제거).

 <router-outlet></router-outlet>

다음으로 AppModule 에 다음 경로를 포함합니다.

 import { RouterModule, Routes } from '@angular/router'; // ... imports: [ // ... RouterModule.forRoot([ { path: '', component: MyNavComponent, children: [ { path: 'add-memory', component: AddMemoryComponent }, { path: 'view-memories', component: ViewMemoriesComponent } ] }, ]), ]

MyNavComponent 를 부모로 설정하고 우리가 만든 두 구성 요소를 자식으로 설정하고 있습니다. 이것은 MyNavComponent<router-outlet> 을 포함했고 이 두 경로 중 하나에 도달할 때마다 <router-outlet> 이 배치된 자식 구성 요소를 렌더링하기 때문입니다.

그런 다음 앱을 제공할 때 다음을 확인해야 합니다.

왼쪽 링크는 메모리 추가 및 내 추억 보기로 대체되었으며 후자가 선택되었습니다. 이제 빈 창에는 ID 번호와 이름이 있는 테이블이 있습니다.

앱 빌드(A Memories Diary)

자, 이제 새로운 추억을 다이어리에 저장할 수 있는 폼을 만들어 보겠습니다.

일부 재료 모듈과 양식 모듈을 app.module.ts 로 가져와야 합니다.

 import { FormsModule } from '@angular/forms'; import { MatCardModule, MatFormFieldModule, MatInputModule, MatDatepickerModule, MatNativeDateModule } from '@angular/material'; // ... Imports:[ // ... MatCardModule, MatFormFieldModule, MatInputModule, MatDatepickerModule, FormsModule, MatNativeDateModule, // ... ]

그런 다음 add-memory.component.html 에 다음 형식을 추가합니다.

 <form #form="ngForm" (ngSubmit)="onSubmit()"> <mat-card class="memory-card"> <mat-card-title> Add a memory </mat-card-title> <mat-card-content> <mat-form-field> <input disabled matInput placeholder="Select the date..." [(ngModel)]="memory.date" name="date" [matDatepicker]="date"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker disabled="false" #date></mat-datepicker> </mat-form-field> <mat-form-field> <textarea placeholder="Enter your memory..." rows="3" maxlength="300" matInput [(ngModel)]="memory.text" name="memory"></textarea> </mat-form-field> </mat-card-content> <mat-card-actions> <button mat-button type="submit">Save me!</button> </mat-card-actions> </mat-card> </form> <pre> {{ memory | json }} </pre>

여기서 우리는 mat-card 를 사용하고 두 개의 필드, datetextarea 을 추가합니다.

[(ngModel)] 을 사용하고 있습니다. 이 Angular 지시문은 나중에 살펴보겠지만 memory.date 표현식과 클래스의 memory 속성을 서로 바인딩합니다. ( [(ngModel)] 은 구문적 설탕입니다. 클래스에서 뷰로, 뷰에서 클래스로 양방향 데이터 바인딩을 수행하는 지름길입니다. 즉, 뷰에 텍스트를 입력하면 memory.date 에 이러한 변경 사항이 반영됩니다. 클래스 인스턴스에서, 그리고 클래스 인스턴스에서 memory.date 를 변경하면 뷰에 변경 사항이 반영됩니다.)

add-memory.component.ts 에서 코드는 다음과 같습니다.

 import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-add-memory', templateUrl: './add-memory.component.html', styleUrls: ['./add-memory.component.scss'] }) export class AddMemoryComponent implements OnInit { memory: any = {}; constructor() { } ngOnInit() { } onSubmit() { console.log(this.memory); } }

여기에서는 ngModel 을 통해 바인딩된 memory 속성을 초기화합니다. AddMemoryComponent 구성 요소가 인스턴스화되면 memory 는 빈 개체가 됩니다. 그런 다음 ngModel 지시문이 실행되면 입력 값을 memory.datememory.text 에 할당할 수 있습니다. 이렇게 하지 Cannot set property 'date/text' of undefined 오류가 발생합니다.

한편, add-memory.component.scss 에는 다음이 필요합니다.

 .memory-card { min-width: 150px; max-width: 400px; width: 100%; margin: auto; } .mat-form-field { width: 100%; }

<pre> {{ memory | json }} </pre> <pre> {{ memory | json }} </pre> 뷰에서 memory 의 현재 상태를 볼 수 있습니다. 브라우저로 이동하면 지금까지의 결과는 다음과 같습니다.

사용자 입력(날짜 및 텍스트)의 내부 표현을 보여주는 "my-memories" 일기 앱 프로토타입

보기에서 (ngSubmit)="onSubmit()" 을 통해 양식을 클래스의 onSubmit 함수에 바인딩했습니다.

 onSubmit() { console.log(this.memory); }

따라서 "Save me!"를 클릭하면 버튼을 누르면 콘솔 로그로 전송된 사용자 입력의 내부 표현을 얻을 수 있습니다.

콘솔 로그에 있는 사용자 입력의 내부 표현입니다.

Angular 6 튜토리얼: Firebase와 연결

다음에 할 일은 추억을 저장하기 위해 프로젝트를 Firebase에 연결하는 것입니다.

먼저 Firebase 콘솔로 이동하여 거기에서 프로젝트를 생성하겠습니다.

Firebase 프로젝트를 추가합니다.

두 번째로 firebaseangularfire2 패키지를 설치합니다.

 npm install firebase angularfire2 --save

그런 다음 이 세 파일 각각에서:

  1. /src/environments/environment.ts
  2. /src/environments/environment.hmr.ts
  3. /src/environments/environment.prod.ts

… Firebase 구성을 추가합니다.

 export const environment = { // ... firebase: { apiKey: '<your-key>', authDomain: '<your-project-authdomain>', databaseURL: '<your-database-URL>', projectId: '<your-project-id>', storageBucket: '<your-storage-bucket>', messagingSenderId: '<your-messaging-sender-id>' } };

프로젝트 개요 페이지에서 "웹 앱에 Firebase 추가"를 클릭하면 위 파일에 필요한 구성 세부정보를 얻을 수 있습니다.

그런 다음 app.module.ts 에 Firebase 모듈을 포함합니다.

 import { AngularFireModule } from 'angularfire2'; import { AngularFireDatabaseModule } from 'angularfire2/database'; import { environment } from '../environments/environment'; // ... Imports:[ // ... AngularFireModule.initializeApp(environment.firebase), AngularFireDatabaseModule, // ... ]

그리고 add-memory.component.ts 에서 데이터베이스를 생성자에 주입하고 폼의 값을 데이터베이스에 저장합니다. Firebase의 푸시 약속이 성공하면 콘솔에 성공을 기록하고 모델을 재설정합니다.

 import { AngularFireDatabase } from 'angularfire2/database'; // ... constructor(private db: AngularFireDatabase) { } // ... onSubmit() { this.memory.date = new Date(this.memory.date).valueOf(); this.db.list('memories').push(this.memory) .then(_ => { this.memory = {} console.log('success') }) } 

Firebase 데이터베이스에 대한 읽기 및 쓰기 액세스를 허용합니다.

익명 사용자가 읽고 쓸 수 있도록 데이터베이스 규칙에 대한 공개 액세스를 허용해야 합니다. 이 설정 사용하면 모든 사용자가 앱 데이터를 읽고/변경하거나 삭제할 수 있습니다. 프로덕션으로 이동하기 전에 그에 따라 규칙을 설정했는지 확인하십시오.

또한 환경 변경 사항을 적용하려면 ng serve 프로세스를 다시 시작해야 합니다.

이제 브라우저로 돌아가서 저장 버튼을 클릭하면 데이터베이스에 메모리가 추가된 것을 볼 수 있습니다.

다이어리 앱의 Firebase 데이터베이스에 테스트 메모리가 추가되었습니다.

메모리를 검색하여 Material 테이블에 표시하는 방법을 살펴보겠습니다.

ng generate @angular/material:material-table --name=view-memories', we automatically got a file 되었습니다. 이 파일에는 가짜 데이터가 포함되어 있으므로 Firebase에서 가져오기를 시작하려면 파일을 변경해야 합니다.

view-memories-datasource.ts 에서 EXAMPLE_DATA 를 제거하고 빈 배열을 설정합니다.

 export class ViewMemoriesDataSource extends DataSource<ViewMemoriesItem> { data: ViewMemoriesItem[] = []; // ...

그리고 getSortedData 에서 필드 이름을 업데이트합니다.

 private getSortedData(data: ViewMemoriesItem[]) { if (!this.sort.active || this.sort.direction === '') { return data; } return data.sort((a, b) => { const isAsc = this.sort.direction === 'asc'; switch (this.sort.active) { case 'text': return compare(a.name, b.name, isAsc); case 'date': return compare(+a.id, +b.id, isAsc); default: return 0; } }); }

view-memories.component.html 에서 열 이름을 메모리 모델의 datetext 로 업데이트합니다. 날짜를 밀리초 형식으로 저장했기 때문에 여기서는 날짜 파이프를 사용하여 표시할 값을 보다 인간 친화적인 날짜 형식으로 변환하고 있습니다. 마지막으로 Firebase에서 비동기식으로 데이터를 로드하므로 페이지 매김에서 [length]="dataSource.data.length" 를 제거합니다.

 <div class="mat-elevation-z8"> <table mat-table #table [dataSource]="dataSource" matSort aria-label="Elements"> <!-- Id Column --> <ng-container matColumnDef="date"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th> <td mat-cell *matCellDef="let row">{{row.date | date:'short'}}</td> </ng-container> <!-- Name Column --> <ng-container matColumnDef="text"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Text</th> <td mat-cell *matCellDef="let row">{{row.text}}</td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator #paginator [pageIndex]="0" [pageSize]="50" [pageSizeOptions]="[25, 50, 100, 250]"> </mat-paginator> </div>

view-memories.component.cssview-memories.component.scss memories.component.scss로 변경하고 테이블 스타일을 설정합니다.

 table{ width: 100%; }

view-memories.component.ts 에서 styleUrls 를 변경하여 위의 이름을 ./view-memories.component.scss 로 변경합니다. 또한 displayedColumns 배열을 ['date', 'text'] 로 업데이트하고 Firebase에서 데이터를 가져오도록 테이블 데이터 소스를 설정합니다.

여기서 일어나는 일은 메모리 목록을 구독하고 데이터를 수신하면 ViewMemoriesDataSource 를 인스턴스화하고 Firebase의 데이터로 데이터 속성을 설정한다는 것입니다.

 this.subscription = this.db.list<ViewMemoriesItem>('memories').valueChanges().subscribe(d=>{ console.log('data streaming'); this.dataSource = new ViewMemoriesDataSource(this.paginator, this.sort); this.dataSource.data = d; });

Firebase는 ReactiveX 스타일의 Observable 배열을 반환합니다.

this.db.list<ViewMemoriesItem>('memories') 'memories' 경로에서 가져온 값)을 ViewMemoriesItem 으로 캐스팅하고 있습니다. 이것은 angularfire2 라이브러리에 의해 처리됩니다.

또한 Angular 구성 요소 수명 주기의 onDestroy 후크 내에 unsubscribe 호출을 포함했습니다.

 import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core'; import { MatPaginator, MatSort } from '@angular/material'; import { ViewMemoriesDataSource, ViewMemoriesItem } from './view-memories-datasource'; import { AngularFireDatabase } from 'angularfire2/database'; import { Subscription } from 'rxjs'; import { map, first } from 'rxjs/operators'; @Component({ selector: 'app-view-memories', templateUrl: './view-memories.component.html', styleUrls: ['./view-memories.component.scss'] }) export class ViewMemoriesComponent implements OnInit, OnDestroy{ @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; dataSource: ViewMemoriesDataSource; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['date', 'text']; subscription: Subscription; constructor(private db: AngularFireDatabase) { } ngOnInit() { this.subscription = this.db.list<ViewMemoriesItem>('memories').valueChanges().subscribe(d=>{ console.log('data streaming'); this.dataSource = new ViewMemoriesDataSource(this.paginator, this.sort); this.dataSource.data = d; }); } ngOnDestroy(): void { this.subscription.unsubscribe(); } }
관련 항목: 실시간 다중 플랫폼 모바일 애플리케이션 빌드: Ionic Framework 및 Firebase를 사용한 예

Firebase 호스팅에 배포

이제 앱을 라이브로 만들기 위해 Firebase 호스팅에 배포해 보겠습니다. 이를 위해 Firebase CLI를 설치하여 firebase 명령을 사용할 수 있도록 합니다.

 npm install -g firebase-tools

이제 Firebase CLI를 사용하여 로그인할 수 있습니다.

 firebase login

Google 계정을 선택하라는 메시지가 표시됩니다.

다음으로 프로젝트를 초기화하고 Firebase 호스팅을 구성합니다.

 firebase init

호스팅 옵션을 선택하겠습니다.

다음으로 경로를 묻는 메시지가 표시되면 dist/my-memories 로 설정합니다. 단일 페이지 앱으로 구성할지(즉, 모든 URL을 /index.html 로 다시 작성) 여부를 묻는 질문에 "예"라고 응답합니다.

마지막으로 "dist/my-memories/index.html 파일이 이미 존재합니다. 덮어쓰기?” 여기서 우리는 "아니오"라고 말할 것입니다.

그러면 제공된 구성으로 firebase.json 구성 파일 .firebaserc 및 firebase.json이 생성됩니다.

마지막 단계는 다음을 실행하는 것입니다.

 ng build --prod firebase deploy

이를 통해 https://my-memories-b4c52.firebaseapp.com/view-memories와 같이 탐색할 URL을 제공하는 Firebase에 앱을 게시하여 내가 게시한 내용을 볼 수 있습니다. 데모.


와우, 튜토리얼을 마치셨습니다! 나는 당신이 그것을 즐겼기를 바랍니다. GitHub에서 전체 코드를 확인할 수도 있습니다.

한 번에 한 단계 씩

Angular는 웹 앱을 빌드하기 위한 매우 강력한 프레임워크입니다. 오랫동안 존재해 왔으며 작고 간단한 앱과 크고 복잡한 앱 모두에서 스스로를 입증했습니다. 여기에서 Angular 6도 예외는 아닙니다.

앞으로 Angular는 웹 컴포넌트(Angular Elements)와 같은 새로운 웹 패러다임을 계속 개선하고 따를 계획입니다. 하이브리드 앱 구축에 관심이 있다면 Angular를 기본 프레임워크로 사용하는 Ionic을 확인할 수 있습니다.

이 튜토리얼에서는 Angular, Material, Firebase 사용을 시작하기 위한 매우 기본적인 단계를 다뤘습니다. 그러나 실제 응용 프로그램의 경우 유효성 검사를 추가해야 하고 응용 프로그램을 더 쉽게 유지 관리하고 확장할 수 있도록 서비스 사용, 재사용 가능한 구성 요소 등과 같은 모범 사례를 따르기를 원할 수 있다는 점을 고려해야 합니다. 그것은 다른 기사의 주제가 되어야 합니다. 바라건대 이 기사가 Angular 개발에 대한 욕구를 불러일으키기에 충분했습니다!

관련: 모든 특전, 번거로움 없음: Angular 9 자습서