新聞中心
獨(dú)立組件入門
在 v14 及更高版本中,獨(dú)立組件提供了一種簡化的方式來構(gòu)建 Angular 應(yīng)用程序。獨(dú)立組件、指令和管道旨在通過減少對(duì) ?NgModule ?的需求來簡化創(chuàng)作體驗(yàn)。現(xiàn)有應(yīng)用程序可以選擇性地以增量方式采用新的獨(dú)立風(fēng)格,而無需任何重大更改。

目前成都創(chuàng)新互聯(lián)公司已為上千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、綿陽服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計(jì)、來安網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
獨(dú)立組件特性可用于開發(fā)人員預(yù)覽。它已準(zhǔn)備好供你嘗試;但它可能會(huì)在穩(wěn)定之前發(fā)生變化。
創(chuàng)建獨(dú)立組件
standalone 標(biāo)志和組件 imports
組件、指令和管道現(xiàn)在可以標(biāo)記為 ?standalone: true?。標(biāo)記為獨(dú)立的 Angular 類不需要在 ?NgModule ?中聲明(如果你嘗試,Angular 編譯器會(huì)報(bào)告錯(cuò)誤)。
獨(dú)立組件直接指定它們的依賴項(xiàng),而不是通過 ?NgModule ?獲取它們。例如,如果 ?PhotoGalleryComponent ?是獨(dú)立組件,它可以直接導(dǎo)入另一個(gè)獨(dú)立組件 ?ImageGridComponent ?:
@Component({
standalone: true,
selector: 'photo-gallery',
imports: [ImageGridComponent],
template: `
...
`,
})
export class PhotoGalleryComponent {
// component logic
}?imports ?也可用于引用獨(dú)立指令和管道。通過這種方式,可以編寫?yīng)毩⒔M件,而無需創(chuàng)建 ?NgModule ?來管理模板依賴項(xiàng)。
在獨(dú)立組件中使用現(xiàn)有的 NgModules
編寫?yīng)毩⒔M件時(shí),你可能希望在組件的模板中使用其他組件、指令或管道。其中某些依賴項(xiàng)可能不會(huì)標(biāo)記為獨(dú)立,而是由現(xiàn)有的 ?NgModule ?聲明和導(dǎo)出。在這種情況下,你可以將 ?NgModule ?直接導(dǎo)入到獨(dú)立組件中:
@Component({
standalone: true,
selector: 'photo-gallery',
// an existing module is imported directly into a standalone component
imports: [MatButtonModule],
template: `
...
`,
})
export class PhotoGalleryComponent {
// logic
}你可以在模板中將獨(dú)立組件與現(xiàn)有的基于 ?NgModule ?的庫或依賴項(xiàng)一起使用。獨(dú)立組件可以充分利用現(xiàn)有的 Angular 庫生態(tài)系統(tǒng)。
在基于 NgModule 的應(yīng)用程序中使用獨(dú)立組件
獨(dú)立組件也可以導(dǎo)入到現(xiàn)有的基于 NgModules 的上下文中。這允許現(xiàn)有應(yīng)用程序(今天使用 NgModules)逐步采用新的獨(dú)立風(fēng)格的組件。
你可以像導(dǎo)入 ?NgModule ?一樣導(dǎo)入獨(dú)立組件(或指令或管道)- 使用 ?NgModule.imports? :
@NgModule({
declarations: [AlbumComponent],
exports: [AlbumComponent],
imports: [PhotoGalleryComponent],
})
export class AlbumModule {}
使用獨(dú)立組件引導(dǎo)應(yīng)用程序
通過使用獨(dú)立組件作為應(yīng)用程序的根組件,可以在沒有任何 ?NgModule ?的情況下引導(dǎo) Angular 應(yīng)用程序。這是使用 ?bootstrapApplication ?API 來完成的:
// in the main.ts file
import {bootstrapApplication} from '@angular/platform-browser';
import {PhotoAppComponent} from './app/photo.app.component';
bootstrapApplication(PhotoAppComponent);
配置依賴注入
引導(dǎo)應(yīng)用程序時(shí),你通常希望配置 Angular 的依賴注入并提供配置值或服務(wù)以在整個(gè)應(yīng)用程序中使用。你可以將這些作為提供者傳遞給 ?bootstrapApplication ?:
bootstrapApplication(PhotoAppComponent, {
providers: [
{provide: BACKEND_URL, useValue: 'https://photoapp.looknongmodules.com/api'},
// ...
]
});獨(dú)立的引導(dǎo)操作基于顯式配置 ?Provider ?列表以進(jìn)行依賴注入。但是,現(xiàn)有的庫可能依賴 ?NgModule ?來配置 DI。例如,Angular 的路由器使用 ?RouterModule.forRoot()? 幫助器在應(yīng)用程序中設(shè)置路由。你可以通過 ?importProvidersFrom ?實(shí)用程序在 ?bootstrapApplication ?中使用這些現(xiàn)有的 ?NgModule ?:
bootstrapApplication(PhotoAppComponent, {
providers: [
{provide: BACKEND_URL, useValue: 'https://photoapp.looknongmodules.com/api'},
importProvidersFrom(
RouterModule.forRoot([/* app routes */]),
),
// ...
]
});
路由和惰性加載
路由器 API 進(jìn)行了更新和簡化,以利用獨(dú)立組件的優(yōu)勢:在許多常見的惰性加載場景中不再需要 ?NgModule?。
惰性加載獨(dú)立組件
任何路由都可以用 ?loadComponent ?惰性加載其路由到的獨(dú)立組件:
export const ROUTES: Route[] = [
{path: 'admin', loadComponent: () => import('./admin/panel.component').then(mod => mod.AdminPanelComponent)},
// ...
];只要加載的組件是獨(dú)立的,就可以用。
一次惰性加載多個(gè)路由
?loadChildren ?操作現(xiàn)在支持加載一組新的子 ?Route?,而無需編寫惰性加載的 ?NgModule ?來導(dǎo)入 ?RouterModule.forChild? 來聲明路由。當(dāng)以這種方式加載的每個(gè)路由都使用獨(dú)立組件時(shí),這會(huì)起作用。
// In the main application:
export const ROUTES: Route[] = [
{path: 'admin', loadChildren: () => import('./admin/routes').then(mod => mod.ADMIN_ROUTES)},
// ...
];
// In admin/routes.ts:
export const ADMIN_ROUTES: Route[] = [
{path: 'home', component: AdminHomeComponent},
{path: 'users', component: AdminUsersComponent},
// ...
];
為路由的子集提供服務(wù)
?NgModule ?的惰性加載 API ( ?loadChildren ?) 在加載路由的惰性加載的子項(xiàng)時(shí)會(huì)創(chuàng)建一個(gè)新的“模塊”注入器。此特性通常可用于僅向應(yīng)用程序中的一部分路由提供服務(wù)。例如,如果 ?/admin? 下的所有路由都使用 ?loadChildren ?邊界來限定范圍,則可以僅向這些路由提供僅限管理的服務(wù)。執(zhí)行此操作需要使用 ?loadChildren ?API,即使惰性加載有問題的路由不是必要的。
路由器現(xiàn)在支持在 ?Route ?上顯式指定其他 ?providers?,這允許相同的范圍限定,而無需惰性加載或 ?NgModule?。例如,?/admin? 路由結(jié)構(gòu)中的范圍服務(wù)將類似于:
export const ROUTES: Route[] = [
{
path: 'admin',
providers: [
AdminService,
{provide: ADMIN_API_KEY, useValue: '12345'},
],
children: [
path: 'users', component: AdminUsersComponent,
path: 'teams', component: AdminTeamsComponent,
],
},
// ... other application routes that don't
// have access to ADMIN_API_KEY or AdminService.
];也可以將 ?providers ?與額外路由配置的 ?loadChildren ?結(jié)合使用,以實(shí)現(xiàn)與惰性加載帶有額外路由和路由級(jí)服務(wù)提供者的 ?NgModule ?相同的效果。此示例配置與上面相同的提供者/子路由,但在惰性加載邊界之后:
// Main application:
export const ROUTES: Route[] = {
// Lazy-load the admin routes.
{path: 'admin', loadChildren: () => import('./admin/routes').then(mod => mod.ADMIN_ROUTES)},
// ... rest of the routes
}
// In admin/routes.ts:
export const ADMIN_ROUTES: Route[] = [{
path: '',
pathMatch: 'prefix',
providers: [
AdminService,
{provide: ADMIN_API_KEY, useValue: 12345},
],
children: [
{path: 'users', component: AdminUsersCmp},
{path: 'teams', component: AdminTeamsCmp},
],
}];請(qǐng)注意這里使用了空路徑路由來定義供所有子路由共享的宿主 ?providers?。
高級(jí)主題
本節(jié)會(huì)更詳細(xì)地介紹僅與更高級(jí)的使用模式相關(guān)的。第一次了解獨(dú)立組件、指令和管道時(shí),你可以安全地跳過本節(jié)。
針對(duì)庫作者的獨(dú)立組件
獨(dú)立的組件、指令和管道可以從導(dǎo)入它們的 ?NgModule ?中導(dǎo)出:
@NgModule({
imports: [ImageCarouselComponent, ImageSlideComponent],
exports: [ImageCarouselComponent, ImageSlideComponent],
})
export class CarouselModule {}此模式對(duì)于發(fā)布一組合作指令的 Angular 庫很有用。在上面的示例中,?ImageCarouselComponent ?和 ?ImageSlideComponent ?需要出現(xiàn)在模板中,以構(gòu)建一個(gè)邏輯上的“輪播小部件”。
作為發(fā)布 ?NgModule ?的替代方案,庫作者可能希望導(dǎo)出一個(gè)合作指令數(shù)組:
export CAROUSEL_DIRECTIVES = [ImageCarouselComponent, ImageSlideComponent] as const;這樣的數(shù)組可以由使用 ?NgModule ?的應(yīng)用程序?qū)氩⑻砑拥?nbsp;?@NgModule.imports?。請(qǐng)注意 TypeScript 的 ?as const? 構(gòu)造的存在:它為 Angular 編譯器提供了正確編譯所需的額外信息,并且是一種推薦的實(shí)踐(因?yàn)樗箤?dǎo)出的數(shù)組從 TypeScript 的角度來看是不可變的)。
依賴注入和注入器層次結(jié)構(gòu)
Angular 應(yīng)用程序可以通過指定一組可用的提供者來配置依賴注入。在典型應(yīng)用中,有兩種不同的注入器類型:
- 具有在 ?
@NgModule.providers? 或 ?@Injectable({providedIn: "..."})? 中配置的服務(wù)提供者的模塊注入器。這些應(yīng)用程序范圍的提供者對(duì)模塊注入器中配置的所有組件以及其他服務(wù)可見。 - 在 ?
@Directive.providers? / ?@Component.providers? 或 ?@Component.viewProviders? 中配置的節(jié)點(diǎn)注入器。這些提供程序僅對(duì)給定組件及其所有子項(xiàng)可見。
環(huán)境注入器
使 ?NgModule ?變成可選的將需要一種新方法來用應(yīng)用程序范圍的提供者配置“模塊”注入器。在獨(dú)立應(yīng)用程序(使用 ?bootstrapApplication ?創(chuàng)建的)中,可以在引導(dǎo)過程中在 ?providers ?選項(xiàng)中配置“模塊”提供程序:
bootstrapApplication(PhotoAppComponent, {
providers: [
{provide: BACKEND_URL, useValue: 'https://photoapp.looknongmodules.com/api'},
{provide: PhotosService, useClass: PhotosService},
// ...
]
});新的引導(dǎo) API 為我們提供了在不使用 ?NgModule ?的情況下配置“模塊注入器”的方法。從這個(gè)意義上說,名稱的“模塊”部分不再相關(guān),我們決定引入一個(gè)新術(shù)語:“環(huán)境注入器”。
可以用以下方法之一配置環(huán)境注入器:
- ?
@NgModule.providers?(在通過 ?NgModule?引導(dǎo)的應(yīng)用程序中); - ?
@Injectable({provideIn: "..."})?(在基于 NgModule 以及“獨(dú)立”應(yīng)用程序中); - ?
bootstrapApplication?調(diào)用中的 ?providers?選項(xiàng)(在完全“獨(dú)立”的應(yīng)用程序中); - ?
Route?配置中的 ?providers?字段。
Angular v14 引入了一種新的 TypeScript 類型 ?EnvironmentInjector ?來表示這種新命名。附帶的 ?createEnvironmentInjector ?API 使得以編程方式創(chuàng)建環(huán)境注入器成為可能:
import {createEnvironmentInjector} from '@angular/core';
const parentInjector = … // existing environment injector
const childInjector = createEnvironmentInjector([{provide: PhotosService, useClass: CustomPhotosService}], parentInjector);環(huán)境注入器還有一個(gè)額外的能力:它們可以在創(chuàng)建環(huán)境注入器時(shí)執(zhí)行初始化邏輯(類似于創(chuàng)建模塊注入器時(shí)執(zhí)行的 ?NgModule ?構(gòu)造函數(shù)):
import {createEnvironmentInjector, ENVIRONMENT_INITIALIZER} from '@angular/core';
createEnvironmentInjector([
{provide: PhotosService, useClass: CustomPhotosService},
{provide: ENVIRONMENT_INITIALIZER, useValue: () => {
console.log("This function runs when this EnvironmentInjector gets created");
}}
]);
獨(dú)立注入器
實(shí)際上,依賴注入器層次結(jié)構(gòu)在使用獨(dú)立組件的應(yīng)用程序中稍微復(fù)雜一些。讓我們考慮以下示例:
// an existing "datepicker" component with an NgModule
@Component({
selector: 'datepicker',
template: '...',
})
class DatePickerComponent {
constructor(private calendar: CalendarService) {}
}
@NgModule({
declarations: [DatePickerComponent],
exports: [DatePickerComponent]
providers: [CalendarService],
})
class DatePickerModule {
}
@Component({
selector: 'date-modal',
template: ' ',
standalone: true,
imports: [DatePickerModule]
})
class DateModalComponent {
}在上面的示例中,組件 ?DateModalComponent ?是獨(dú)立的 - 它可以直接使用,并且沒有需要導(dǎo)入才能使用它的 NgModule。但是,?DateModalComponent ?有一個(gè)依賴項(xiàng) ?DatePickerComponent?,它是通過其 NgModule(?DatePickerModule?)導(dǎo)入的。此 NgModule 可以聲明 ?DatePickerComponent ?正常運(yùn)行所需的提供者(在本例中為:?CalendarService?)。
當(dāng) Angular 創(chuàng)建獨(dú)立組件時(shí),它需要知道當(dāng)前注入器具有獨(dú)立組件依賴項(xiàng)的所有必要服務(wù),包括基于 NgModules 的服務(wù)。為了保證這一點(diǎn),在某些情況下,Angular 會(huì)創(chuàng)建一個(gè)新的“獨(dú)立注入器”作為當(dāng)前環(huán)境注入器的子項(xiàng)。今天,這種情況發(fā)生在所有引導(dǎo)的獨(dú)立組件上:它將是根環(huán)境注入器的子項(xiàng)。相同的規(guī)則適用于動(dòng)態(tài)創(chuàng)建的(例如,由路由器或 ?ViewContainerRef ?API)獨(dú)立組件。
創(chuàng)建了一個(gè)單獨(dú)的獨(dú)立注入器,以確保獨(dú)立組件導(dǎo)入的提供程序與應(yīng)用程序的其余部分“隔離”。這讓我們將獨(dú)立組件視為真正獨(dú)立的部分,不能將它們的實(shí)現(xiàn)細(xì)節(jié)“泄漏”給應(yīng)用程序的其余部分。
網(wǎng)站名稱:創(chuàng)新互聯(lián)Angular教程:Angular獨(dú)立組件
網(wǎng)頁URL:http://fisionsoft.com.cn/article/dpepijs.html


咨詢
建站咨詢
