Учебник по Angular 6: новые функции с новой силой
Опубликовано: 2022-03-11Угловой 6 вышел! Самые выдающиеся изменения коснулись интерфейса командной строки и способа внедрения сервисов. Если вы хотите написать свое самое первое приложение Angular 6 — или приложение Angular/Firebase — в этом руководстве мы рассмотрим основные шаги начальной настройки и создадим небольшое приложение-дневник.
Угловой 6: Основы
Если вы никогда раньше не использовали Angular, позвольте мне кратко описать его и то, как он работает.
Angular — это среда JavaScript, предназначенная для поддержки создания одностраничных приложений (SPA) как для настольных компьютеров, так и для мобильных устройств.
Платформа включает в себя полный набор директив и модулей, которые позволяют легко реализовать некоторые из наиболее распространенных сценариев для веб-приложения, такие как навигация, авторизация, формы и отчетность. Он также поставляется со всеми необходимыми пакетами для добавления тестов с использованием платформы Jasmine и их запуска с помощью средств запуска тестов Karma или Protractor.
Архитектура Angular основана на компонентах, шаблонах, директивах и сервисах. Он предоставляет встроенный механизм внедрения зависимостей для ваших служб, а также двустороннюю привязку данных для соединения ваших представлений с кодом вашего компонента.
Angular использует TypeScript, типизированный надмножество JS, и упростит некоторые вещи, особенно если вы имеете опыт работы с типизированным языком.
Angular 6: новые возможности
Краткий обзор новых функций в Angular 6:
- Политика синхронизации основных номеров версий для пакетов фреймворка (
@angular/core,@angular/common,@angular/compilerи т. д.), CLI, Material и CDK. Это поможет сделать кросс-совместимость более понятной в будущем: по номеру версии вы можете сказать, совместимы ли ключевые пакеты друг с другом. - Новые команды командной строки
ng:-
ng updateдля интеллектуального обновления версий пакетов, обновления версий зависимостей и их синхронизации. (Например, при запускеng update @angular/coreбудут обновлены все фреймворки, а также RxJS.) Он также запустит схемы , если они включены в пакет. (Если более новая версия содержит критические изменения, требующие изменений в коде, схема обновит ваш код за вас.) -
ng addдля добавления новых пакетов (и запуска скриптов, если применимо)
-
- Службы теперь ссылаются на модули, которые будут их предоставлять, а не на модули, ссылающиеся на службы, как раньше.
В качестве примера того, что означает это последнее изменение, где ваш код выглядел так:
@NgModule({ // ... providers: [MyService] })… с этим конкретным изменением в Angular 6 это будет выглядеть так:
@Injectabe({ providedIn: 'root', })Такие поставщики называются древовидными провайдерами и позволяют компилятору удалять сервисы, на которые нет ссылок, что приводит к уменьшению размера пакетов.
Угловой 6 интерфейс командной строки
Интерфейс командной строки ng является очень важной частью Angular и позволяет вам двигаться быстрее при кодировании вашего приложения.
С помощью интерфейса командной строки вы можете очень легко формировать исходную настройку приложения, создавать новые компоненты, директивы и т. д., а также создавать и запускать приложение в локальной среде.
Создание проекта Angular 6
Ладно, хватит разговоров. Давайте запачкаем руки и начнем кодировать.
Для начала вам понадобятся Node.js и npm, установленные на вашем компьютере.
Теперь давайте продолжим и установим CLI:
npm install -g @angular/cli Это установит команду ng CLI глобально из-за ключа -g .
Получив это, мы можем получить исходный каркас для нашего приложения с помощью ng new :
ng new my-memories --style=scss Это создаст папку my-memories , создаст все необходимые файлы, чтобы подготовить первоначальную настройку к запуску, и установит все необходимые пакеты. Переключатель --style=scss является необязательным и настроит компилятор для компиляции файлов SCSS в CSS, который нам понадобится позже.
После завершения установки вы можете cd my-memories и запустить ng serve . Это запустит процесс сборки и локальный веб-сервер, который обслуживает ваше приложение по адресу http://localhost:4200 .
Что происходит за кулисами, так это то, что CLI транспилирует все .ts (файлы TypeScript) в vanilla JS, собирает все необходимые зависимости из папки пакетов node_modules и выводит результат в виде набора файлов, которые обслуживаются через локальный веб-сервер. который работает на порту 4200.
Файлы проекта
Если вы не знакомы со структурой папок проекта Angular, самое важное, что вам нужно знать, это то, что весь код, связанный с приложением, находится внутри папки src . Обычно вы создаете все свои модули и директивы в этой папке в соответствии с архитектурой вашего приложения (например, пользователь, корзина, продукт).
Начальная настройка
Итак, у нас есть начальная настройка нашего приложения. Давайте начнем вносить некоторые изменения.
Прежде чем мы начнем, давайте немного покопаемся в папке 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 вставляет код нашего компонента.
Мы найдем файл app/app.component.ts , в котором селектор app-root соответствует тому, что находится в файле index.html .
Компонент представляет собой оформленный класс 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 отображает значение свойства title класса и обновляет его каждый раз, когда оно изменяется.
<!--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!'; } ...Мы увидим, как компилятор обработает наше изменение, а браузер обновится, чтобы отобразить наш обновленный заголовок.
Это означает, что ng serve в Angular 6 следит за изменениями в наших файлах и отображает их каждый раз, когда в какой-либо файл вносятся изменения.
Чтобы сделать программирование более дружественным и избежать полного обновления страницы каждый раз, когда мы вносим изменения, мы можем воспользоваться преимуществом горячей замены модулей webpack (HMR), которая просто обновляет фрагмент JS/CSS, который был изменен, вместо того, чтобы производить полное обновление до показать свои изменения.
Настройка 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" } ] }, // ... И в projects → my-memories → architect → serve → configurations :
"projects": { "my-memories": { "architect": { // ... "serve": { // ... "configurations": { "hmr": { "browserTarget": "my-memories:build:hmr" }, // ... Теперь обновите tsconfig.app.json , включив в него необходимые types (ну, тип), добавив это compilerOptions :
"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)); } Что мы здесь делаем, так это заставляем bootstrap вызывать анонимную функцию, а затем спрашиваем, истинен ли флаг environment.hmr . Если это так, мы вызываем ранее определенную функцию из hmr.ts , которая включила горячую замену модуля; в противном случае мы загружаем его, как раньше.
Теперь, когда мы запускаем ng serve --hmr --configuration=hmr , мы будем вызывать конфигурацию hmr , и когда мы будем вносить изменения в файлы, мы будем получать обновления без полного обновления. Первый --hmr для веб-пакета, а --configuration=hmr для Angular для использования среды hmr .
Прогрессивное веб-приложение (PWA)
Чтобы добавить поддержку Angular 6 PWA и включить автономную загрузку приложения, мы можем использовать одну из новых команд CLI, ng add :
ng add @angular/[email protected] Обратите внимание, что я добавляю версию, так как последняя версия, когда я писал это руководство, выдавала ошибку. (Вы можете попробовать без него и проверить, работает ли он для вас, просто используя ng add @angular/pwa .)
Итак, после того, как мы запустим команду, мы увидим много изменений в нашем проекте. Наиболее важные изменения заключаются в том, что он добавил:
- Ссылка на
manifest.jsonв файле ресурсовangular.json, чтобы он был включен в выходные данные сборки, а также"serviceWorker": trueв производственных сборках. -
ngsw-config.jsonс начальной настройкой для кэширования всех файлов, необходимых для запуска приложения. - Метатег
manifest.jsonв файлеindex.html - Сам файл
manifest.jsonс базовой конфигурацией приложения. - Сервисный работник загружается в модуль приложения
ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })(обратите внимание, что сервисный работник будет включен только в производственных средах)
Итак, теперь это означает, что когда пользователь впервые обращается к URL-адресу, файлы будут загружены. После этого, если пользователь попытается получить доступ к URL-адресу без сетевой службы, приложение по-прежнему будет работать, извлекая эти кэшированные файлы.
Добавление библиотеки пользовательского интерфейса Material Angular 6
На данный момент у нас есть первоначальная настройка, и мы готовы приступить к созданию нашего приложения. Чтобы использовать уже созданные компоненты, мы можем использовать версию Material для Angular 6.
Чтобы установить пакет material в наше приложение, мы снова воспользуемся ng add :
ng add @angular/materialПосле того, как мы запустим это, мы увидим несколько добавленных новых пакетов и некоторую базовую конфигурацию стиля:
-
index.htmlвключает шрифт Roboto и значки материалов. -
BrowserAnimationsModuleдобавлен в нашAppModule -
angular.jsonуже включена индиго-розовая тема.
Вам нужно будет перезапустить ng serve , чтобы выбрать тему, или вы можете выбрать другую готовую тему.
Базовая компоновка
Чтобы получить первоначальный макет sidenav, мы будем использовать схемы, поставляемые с материалом. Но это нормально, если вы хотите использовать другой макет.
(Короче говоря, схемы позволяют применять преобразования к проекту: вы можете создавать, изменять или удалять файлы по мере необходимости. В этом случае он формирует макет sidenav для нашего приложения.)
ng generate @angular/material:material-nav --name=my-navЭто создаст компонент sidenav с минимальной настройкой, готовый к запуску. Разве это не здорово?
Он также включил все необходимые модули в наш app.module.ts .
Поскольку мы используем SCSS, нам нужно переименовать файл my- my-nav.component.css в my-nav.component.scss , а в my-nav.component.ts обновить соответствующую ссылку styleUrls , чтобы использовать новое имя.
Теперь, чтобы использовать новый компонент, давайте перейдем к app.component.html и удалим весь исходный код, оставив только:
<app-my-nav></app-my-nav>Когда мы вернемся в браузер, вот что мы увидим:
Давайте обновим ссылки, чтобы иметь только два нужных параметра.
Во-первых, давайте создадим два новых компонента:
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 в качестве родителя, а два созданных нами компонента — в качестве дочерних. Это связано с тем, что мы включили <router-outlet> в MyNavComponent , и всякий раз, когда мы сталкиваемся с одним из этих двух маршрутов, мы будем отображать дочерний компонент, где был размещен <router-outlet> .
После этого, когда мы обслуживаем приложение, мы должны увидеть:
Создайте приложение (дневник воспоминаний)
Хорошо, теперь давайте создадим форму для сохранения новых воспоминаний в наш дневник.
Нам нужно импортировать некоторые модули материалов и модуль форм в наш 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 и добавляем два поля, date и textarea .
Обратите внимание, что мы используем [(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); } } Здесь мы инициализируем свойство memory , привязанное через ngModel . При создании экземпляра компонента AddMemoryComponent memory будет пустым объектом. Затем, когда директива ngModel запустится, она сможет присвоить входное значение memory.date и memory.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 в представлении. Если мы перейдем к браузеру, вот результат:
В представлении мы привязали форму через (ngSubmit)="onSubmit()" к функции onSubmit в классе.
onSubmit() { console.log(this.memory); }Поэтому, когда вы нажимаете кнопку «Спасите меня!» кнопку, вы получите внутреннее представление пользовательского ввода, отправленного в журнал консоли:
Учебник по Angular 6: подключение к Firebase
Далее мы подключим наш проект к Firebase, чтобы сохранить наши воспоминания.
Сначала мы перейдем в консоль Firebase и создадим там проект.
Во-вторых, мы установим пакеты firebase и angularfire2 :
npm install firebase angularfire2 --saveИ затем в каждом из этих трех файлов:
-
/src/environments/environment.ts -
/src/environments/environment.hmr.ts -
/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 в ваше веб-приложение» на странице обзора проекта.
После этого мы включим модули Firebase в наш app.module.ts :
import { AngularFireModule } from 'angularfire2'; import { AngularFireDatabaseModule } from 'angularfire2/database'; import { environment } from '../environments/environment'; // ... Imports:[ // ... AngularFireModule.initializeApp(environment.firebase), AngularFireDatabaseModule, // ... ] А в add-memory.component.ts базу в конструкторе и сохраняем значения из формы в базу. Когда push-обещание от 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') }) } Вам нужно будет разрешить публичный доступ к правилам базы данных, чтобы анонимные пользователи могли читать и писать в нее. Обратите внимание , что с этой настройкой любой пользователь сможет читать/изменять/удалять данные вашего приложения. Убедитесь, что вы настроили свои правила соответствующим образом, прежде чем переходить к производству.
Кроме того, чтобы принять изменения среды, вам необходимо перезапустить процесс ng serve .
Теперь, когда мы вернемся в браузер и нажмем кнопку сохранения, мы увидим, что память была добавлена в базу данных:
Давайте посмотрим, как мы можем получить наши воспоминания и отобразить их в таблице материалов.
Когда мы создали таблицу с помощью ng generate @angular/material:material-table --name=view-memories', we automatically got a file view-memories/view-memories-datasource.ts`. Этот файл содержит поддельные данные, поэтому нам нужно изменить его, чтобы начать извлечение из 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 мы обновим имена столбцов до date и text из нашей модели памяти. Обратите внимание, что, поскольку мы сохранили дату в миллисекундном формате, здесь мы используем канал даты для преобразования отображаемого значения в более удобный для человека формат даты. Наконец, мы удаляем [length]="dataSource.data.length" из пагинатора, так как мы будем асинхронно загружать данные из Firebase:
<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.css на view-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 возвращает массив Observable в стиле ReactiveX.
Обратите внимание, что мы this.db.list<ViewMemoriesItem>('memories') — значения, извлеченные из пути 'memories' — к ViewMemoriesItem . Об этом позаботится библиотека angularfire2 .
Мы также включили вызов отмены unsubscribe в хук onDestroy жизненного цикла компонента Angular.
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(); } }Развертывание на хостинге Firebase
Теперь, чтобы запустить наше приложение, давайте развернем его на хостинге Firebase. Для этого мы установим интерфейс командной строки Firebase, который сделает доступной команду firebase :
npm install -g firebase-toolsТеперь мы можем использовать Firebase CLI для входа в систему:
firebase loginВам будет предложено выбрать свою учетную запись Google.
Далее мы инициализируем проект и настроим Firebase Hosting:
firebase initМы просто выберем опцию Хостинг.
Далее, когда нас спросят о пути, мы установим его на dist/my-memories . Когда нас спросят, следует ли настроить его как одностраничное приложение (т. е. переписать все URL-адреса на /index.html ), мы ответим «да».
Наконец, мы нажимаем: «Файл dist/my-memories/index.html уже существует. Переписать?» Здесь мы скажем «нет».
Это создаст файлы конфигурации Firebase .firebaserc и firebase.json с предоставленной конфигурацией.
Последний шаг — запустить:
ng build --prod firebase deployИ с этим мы опубликуем приложение в Firebase, который предоставляет нам URL-адрес для перехода, например https://my-memories-b4c52.firebaseapp.com/view-memories, где вы можете просмотреть мои собственные опубликованные демо.
Вау, вы прошли обучение! Я надеюсь, что вам понравилось. Вы также можете проверить полный код на GitHub.
Один шаг за раз
Angular — очень мощный фреймворк для создания веб-приложений. Он существует уже давно и хорошо зарекомендовал себя как для небольших простых приложений, так и для больших и сложных — Angular 6 здесь не исключение.
В дальнейшем Angular планирует продолжать совершенствоваться и следовать новым веб-парадигмам, таким как веб-компоненты (Angular Elements). Если вы заинтересованы в создании гибридных приложений, вы можете попробовать Ionic, который использует Angular в качестве базовой платформы.
В этом руководстве были рассмотрены самые основные шаги, чтобы начать использовать Angular, Material и Firebase. Но вы должны принять во внимание, что для реальных приложений вам нужно будет добавить проверку, а чтобы упростить обслуживание и масштабирование вашего приложения, вы, вероятно, захотите следовать передовым методам, таким как использование служб, повторно используемые компоненты и т. д. Это должно быть предметом другой статьи — надеюсь, этой было достаточно, чтобы пробудить ваш аппетит к разработке Angular!
