В этой части статьи я расскажу о важных возможностях Angular, которые нам понадобятся для настройки и структурирования проекта. Этими функциями являются инициализатор приложения и настройка маршрутизации с помощью модуля.
Прежде чем мы начнем, если вы не понимаете, с чего начать, пожалуйста, прочитайте мою предыдущую часть этой серии статей.
Предпосылки
- Узел JS 10 или выше
- Угловой интерфейс командной строки
- Коммуникативная версия 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 }]
Как работает атрибут провайдера
Провайдеры создадут экземпляр зависимости, чтобы он мог получить доступ к приложению или модулям, другим экземплярам, таким как службы, компоненты и модули, связанные с угловыми компонентами, директивами, каналами и другими службами, которые могут получить доступ к этой зависимости во время выполнения приложения.
- provide: свойство Provide содержит токен, который служит ключом как для определения местоположения значения зависимости, так и для настройки инжектора.
- Второй атрибут сообщает инжектору, как создать значение зависимости. это может быть
useClass
,useValue
,userFactory
,userExisting
. Мы используемuserFactory
, потому что мы используем фабричную функцию, чтобы сообщить инжектору, как создать значение. - deps: это массив, мы можем внедрить зависимость для введенного провайдера, который является фабричной функцией, сервисами или классом.
- 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 по ссылкам