В этой части статьи я расскажу о важных возможностях Angular, которые нам понадобятся для настройки и структурирования проекта. Этими функциями являются инициализатор приложения и настройка маршрутизации с помощью модуля.

Прежде чем мы начнем, если вы не понимаете, с чего начать, пожалуйста, прочитайте мою предыдущую часть этой серии статей.



Предпосылки

  1. Узел JS 10 или выше
  2. Угловой интерфейс командной строки
  3. Коммуникативная версия PyCharm

Инициализатор приложений

Хук инициализатора приложения предоставляет функцию для внедрения кода, служб и API, потребляющих данные во время запуска приложения, он будет выполняться во время ускорения приложения. он возвращает обещание и гарантирует, что инициализация приложения не будет завершена до тех пор, пока обещание не будет разрешено.

В этом руководстве мы загружаем файл конфигурации JSON с некоторыми данными, а также функцией фабрики uisng и поставщиком.

Сначала создайте файл JSON с именем app.config.json at /src с этими данными, указанными ниже в

{
  "app_name": "New Example Application",
  "api_end_point": "This is new Endpoint",
  "copy_right_info": "This is copyright by",
  "development_company": "Development Company"
}

Затем нам нужно добавить путь от файла app.config.json к файлу angular.json, чтобы он мог загрузиться в путь http://<hostname or IP>:<port>/app.config.json приложения. Для этого добавляем файл /src/app.config.json в массив build и test assets в качестве элемента

assets: [
  ......
  "src/app.config.json"
]

Если мы используем внешнюю конфигурацию с другого сервера, мы не добавляем ее в файл angular.json.

Создает модель, которая используется для обработки файла конфигурации JSON во время выполнения приложения.

> ng g class Models/AppConfiguration

Добавьте приведенные ниже фрагменты кода в папку app-config в папке Models, я объявляю абстрактный класс, поэтому я могу использовать наследование или композицию или расширять его до другого класса, если это необходимо.

export abstract class AppConfiguration {
    app_name: string,
    api_end_point: string,
    copy_right_info: string,
    development_company: string
}

Создайте класс обслуживания в корне файла приложения /src/app/AppInitService.ts

> ng g service AppInit

Он генерирует два файла в следующем каталоге

CREATE src/app/app-init.service.spec.ts (363 bytes)
CREATE src/app/app-init.service.ts (136 bytes)

Затем я добавлю следующий код в файл app-init.service.ts.

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { AppConfiguration } from './models/app-configuration';
@Injectable({
   providedIn: 'root'
})
export class AppInitService extends AppConfiguration {
    constructor(private httpClient: HttpClient) {
     super()
    }
    
    async load(): Promise<any> {
      const data = await this.httpClient.get<AppConfiguration>(`app.config.json`).toPromise();
      this.app_name = data.app_name, 
      this.api_end_point = data.api_end_point,
      this.copy_right_info = data.copy_right_info,
      this.development_company = data.development_company;
    }
}

Что делает Super()?

Super() в конструкторе вызовет все свойства, атрибуты, функции или методы абстрактного класса или суперкласса. В этом коде мы расширяем класс AppConfiguration в классе AppInitService, чтобы вызвать атрибут Configuration класса AppConfiguration. Разработчику необходимо добавить super() для доступа к поведению и свойствам класса Super.

Добавьте зависимость HttpClient к constructor элемента service, следуя шаблону dependency injection. поэтому мы можем получить доступ к sevice классу каждой функции и события.

Об асинхронности и toPromise()

APP_INITILIZER, необходимо обещать возврат, чтобы загрузить всю информацию перед инициализацией углового приложения. Если все настроено, если все в порядке, мы можем использовать оператор Promise resolve, а если APP_INITILIZER не okay, мы можем reject его. Таким образом, разработчик может уведомить о том, что конфигурация приложения или информация о запуске в порядке во время выполнения. мы используемasync await, что уже делает функцию многообещающей.

const data = await this.httpClient.get<AppConfiguration>(`app.config.json`).toPromise();

В этом фрагменте кода мы ожидаем формы результата app.config.json с помощью http-вызова, после чего мы оборачиваем форму by toPromise() .

Затем мы добавляем APP_INITIALIZER в файл app.module.ts.

import { Core, APP_INITIALIZER } from '@angular/core';
import { AppInitService } from './app-init.service';

Создайте фабричную функцию для app.module.ts перед объявлением @NgModule в файле.

Factory — это угловая функция, которая используется для возврата значений. Значение по запросу создается фабрикой всякий раз, когда оно требуется службе или контроллеру. После создания значения оно повторно используется для всех служб и контроллеров.

Версия ES6 для заводской функции

export const  appStartupServiceFactory =  (startupService: AppInitService): Function  => () => startupService.load()

Обычная версия Javascript фабричной функции

export function appStartupServiceFactory (startupService: AppInitService): Function {
   return function () {
         return startupService.load()
   }
}

Добавьте поставщика услуг для APP_INITIALIZER и укажите зависимость как AppInitService.

providers: [{
  provide: APP_INITIALIZER,
  useFactory: appStartupServiceFactory,
  deps: [AppInitService],
  multi: true
 }]

Как работает атрибут провайдера

Провайдеры создадут экземпляр зависимости, чтобы он мог получить доступ к приложению или модулям, другим экземплярам, ​​таким как службы, компоненты и модули, связанные с угловыми компонентами, директивами, каналами и другими службами, которые могут получить доступ к этой зависимости во время выполнения приложения.

  1. provide: свойство Provide содержит токен, который служит ключом как для определения местоположения значения зависимости, так и для настройки инжектора.
  2. Второй атрибут сообщает инжектору, как создать значение зависимости. это может быть useClass, useValue, userFactory, userExisting. Мы используем userFactory, потому что мы используем фабричную функцию, чтобы сообщить инжектору, как создать значение.
  3. deps: это массив, мы можем внедрить зависимость для введенного провайдера, который является фабричной функцией, сервисами или классом.
  4. multi: multi:true зарегистрирует множественный обработчик для определенного события или хука, такого как APP_INITIALIZER., он создаст множественный экземпляр для обработки событий angular.

Для проверки APP_INITIALIZATION работает отлично. Мы добавляем журнал консоли в файл home.component.ts на HomeComponent constractor.

constructor(private service:PostService, private configService:  AppInitService) {
     console.log('config service',configService.app_name)
}

Когда мы просматриваем маршрут home, вы видите в консоли, что он уже загружает значение формы хука APP_INITIALIZER.

Модуль маршрутизации

> ng g m components/admin --routing

Он создает два файла, связанных с модулем и маршрутизацией.

src/app/components/admin/admin.module.ts
src/app/components/admin/admin-routing.module.ts

Затем создайте компонент администратора, выполнив следующую команду

> ng g c components/admin

Он генерирует четыре файла, которые мы уже обсуждали в первой части нашего руководства, и обновляет некоторый код в файле admin.module.ts, обновляет, чтобы добавить компонент администратора в declarations атрибут @NgModule.

CREATE src/app/components/admin/admin.component.scss (0 bytes)
CREATE src/app/components/admin/admin.component.html (20 bytes)
CREATE src/app/components/admin/admin.component.spec.ts (619 bytes)
CREATE src/app/components/admin/admin.component.ts (272 bytes)
UPDATE src/app/components/admin/admin.module.ts (455 bytes)

Измененный код показан ниже…

....
import { AdminComponent } from './admin.component';
@NgModule({
   declarations: [AdminComponent],
    .....
})
export class AdminModule { }

Затем создайте два компонента с именами login и register для административного модуля, выполнив следующую команду для компонента login.

> ng g c components/admin/components/login

Для компонента регистрации

> ng g c components/admin/components/registration

Он также обновляет файл admin.module.ts, добавляя компонент в раздел declaration декоратора @NgModule.

import { RegistrationComponent } from './components/registration/registration.component';
import { LoginComponent } from './components/login/login.component';
@NgModule({
   declarations: [LoginComponent, RegistrationComponent, AdminComponent],
 ....
})
export class AdminModule { }

Перед запуском включите маршрутизацию AdminModule, мы должны проверить тот код, который уже добавлен angular cli в файл admin.module.ts, в противном случае вам придется добавить его вручную в файл app.module.ts, следуя приведенному ниже коду.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LoginComponent } from './components/login/login.component';
import { RegistrationComponent } from './components/registration/registration.component';
import { AdminComponent } from './admin.component';
import {AdminRoutingModule} from './admin-routing.module'
@NgModule({
   declarations: [LoginComponent, RegistrationComponent, AdminComponent],
    imports: [
    CommonModule,
    AdminRoutingModule
   ]
})
export class AdminModule { }

Добавьте все компоненты, относящиеся к модулю admin, в файл admin.module.ts LoginComponent, RegisterComponent и AdminComponent. Должен быть добавлен в атрибут declarations дакоратора @NgModule.

Необходимо добавить AdminRoutingModule , потому что мы объявляем всю маршрутизацию модуля admin там.

После этого мы должны изменить файл admin-routing.module.ts, как показано ниже.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminComponent } from './admin.component';
import { LoginComponent } from './components/login/login.component';
import { RegistrationComponent } from './components/registration/registration.component';
const routes: Routes = [
    {path: '', component: AdminComponent, 
      children: [
       {path: 'login', component: LoginComponent},
       {path: 'register', component: RegistrationComponent}
      ]}
];
@NgModule({
   imports: [RouterModule.forChild(routes)],
   exports: [RouterModule]
})
export class AdminRoutingModule { }

Что такое RouterModule.forRoot() и RouterModule.forChield()?

  • Метод forRoot() создает NgModule, который содержит все директивы, заданные маршруты и сам сервис Router.
  • Метод forChild() создает NgModule, который содержит все директивы и заданные маршруты, но не включает службу Router.

Импортируйте все компоненты, относящиеся к модулю admin. Добавьте путь маршрутизации и компонент для handle основного маршрута. В Main Route мы должны указать chield routes. AdminComponent является основным Route администратора, поэтому мы делаем путь пустым, мы предоставляем /admin URL-адрес браузера, который он обслуживает AdminComponent , добавляем дочерние элементы LoginComponent и RegisterComponent , поэтому /admin/login и /admin/register будут работать с этими двумя компонентами.

Затем мы должны добавить `‹router-outlet›` в файл admin.component.html.

<router-outlet></router-outlet>

Без добавления его в html-шаблон ‹router-outlet› Angular не может обслуживать маршрутизацию модуля admin.

Затем мы лениво загружаем код adminModule в appRoutingModule by following в файл app-routing.module.ts.

const routes: Routes = [
   ........
   {path: 'admin', loadChildren: () => import("./components/admin/admin.module").then(m => m.AdminModule)}
];

Добавьте следующую HTML-кнопку в файл app.component.html для навигации.

<a href="/admin/login" mat-raised-button color="primary">Admin Login</a>
<a href="/admin/register" mat-raised-button color="primary">Admin Register</a>

Затем перейдите в браузер и найдите эти два routes

Весь код вы найдете на github по ссылкам



В следующем уроке я расскажу о том, как докеризировать приложение Angular и развернуть его в облачной службе…………