最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析Angular2子模塊以及異步加載

 更新時間:2017年04月24日 15:47:48   作者:Coding I am  
本篇文章主要介紹了淺析Angular2子模塊以及異步加載,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

用Angular2開發(fā)一個大型的應用,我們通常都需要分模塊進行開發(fā)。例如將某一個功能的相關(guān)頁面和功能放在一個模塊里面,這樣既可以實現(xiàn)系統(tǒng)的松耦合,給開發(fā)和后期的維護帶來很大的便利。同時,對于子模塊,我們還可以使用延時加載,這樣可以減少初始加載的文件的大小。在這篇文章中,我們就來看看在Angular2框架下怎么實現(xiàn)子模塊及其延時加載。

可以在這里查看本文使用的實例 。該實例基于上篇文章Angular2使用Guard和Resolve進行驗證和權(quán)限控制 所用的實例,并在它基礎(chǔ)上添加了一個lazy的模塊,以及將現(xiàn)有的todo模塊配置成延時加載方式。

為了體現(xiàn)啟用延時加載前后的包的大小變化,以及啟用壓縮后的變化,在這個教程里面,使用了angular-cli創(chuàng)建項目腳手架,并用它來進行測試和打包。有關(guān)angular-cli的使用請查看 官網(wǎng) 。在這篇文章我們使用的angular-cli的版本是1.0.0-beta.21。如果你使用的是別的版本,可能結(jié)果就會不一樣。甚至有些錯誤,我們在最后會說明當前版本angular-cli的bug。

模塊設(shè)計

在開發(fā)Angular2應用時,像組件設(shè)計、路由設(shè)計以外,對于一個較大型的應用,我們還需要設(shè)計模塊。例如,將一個應用分成幾個功能模塊,以及有哪些公用模塊。公用模塊里面應該放公用的service類,例如權(quán)限驗證、登錄、獲取用戶信息、全局的錯誤處理、工具類等,還有封裝的指令或組件。而在某一個功能模塊里面,只處理這個模塊里面的業(yè)務(wù),盡量不和其他模塊交互。

拿之前教程中的TodoList應用來說,只有home頁面和2個todo頁面,我們把todo相關(guān)的功能放在一個子模塊里面,為了演示,又加了一個簡單的名字叫l(wèi)azy的模塊。我們將把todo模塊和lazy模塊配置成延時加載的模塊。

子模塊開發(fā)

接下來再看看子模塊的開發(fā)。其實在之前的例子中,就把todo相關(guān)的組件放在了一個模塊里面。但是卻沒有強調(diào)子模塊開發(fā)需要注意的地方,甚至有些配置可能沒有采用子模塊的方式進行配置。這里,我們就主要說明一下需要注意的地方,如果要查看完整的代碼,請參考 實例源代碼 。

子模塊路由

首先需要注意的是路由。在之前的例子中,我們把todo相關(guān)的路由定義在一個文件中,然后在app的路由定義中把所有路由合并到一起。 todo.routes.ts 的內(nèi)容如下:

// 省略import
export const TodoRoutes: Route[] = [
  {
    path: 'todo',
    canActivateChild: [MyTodoGuard],
    children: [
      { path: 'list', component: TodoListComponent, resolve: { todos: MyTodoResolver } },
      { path: 'detail/:id', component: TodoDetailComponent, canDeactivate: [ CanLeaveTodoDetailGuard ] }
    ]
  }
];

然后在 app.routes.ts 中定義一個路由模塊:

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  ...TodoRoutes // 這里就是將TodoRoutes列表里的內(nèi)容合并到routes
];
@NgModule({
 imports: [ RouterModule.forRoot(routes) ],
 exports: [ RouterModule ]
})
export classAppRoutingModule{ }

最后,在AppModule里面引入這個路由模塊。

這種方式實現(xiàn)的路由無法實現(xiàn)子模塊的延時加載,要實現(xiàn)延時加載,首先要將todo模塊的路由修改成子路由模塊,也就是要修改 todo.routes.ts

// 省略import
export const TodoRoutes: Route[] = [
  {
    path: 'todo',
    canActivateChild: [MyTodoGuard],
    children: [
      { path: 'list', component: TodoListComponent, resolve: { todos: MyTodoResolver } },
      { path: 'detail/:id', component: TodoDetailComponent, canDeactivate: [ CanLeaveTodoDetailGuard ] }
    ]
  }
];
// 通過下面的方式定義了一個子路由模塊
@NgModule({
 imports: [ RouterModule.forChild(TodoRoutes) ],
 exports: [ RouterModule ]
})
export classTodoRoutingModule{ }

這里,我們定義了一個子路由模塊, TodoRoutingModule ,它使用 RouterModule.forChild(TodoRoutes) 來創(chuàng)建。跟整個App的路由模塊比較的話,主路由模塊使用 RouterModule.forRoot(routes) 來定義。

定義好了子路由模塊,我們就在子模塊里面引入它既可:

// 省略import
@NgModule({
 imports: [CommonModule, FormsModule, TodoRoutingModule ],
 declarations: [TodoListComponent, TodoDetailComponent, TodoItemComponent],
 providers: [TodoService, MyTodoResolver, MyTodoGuard, CanLeaveTodoDetailGuard]
})
export classTodoModule{}

這樣,我們就定義好了一個子模塊。當用戶打開 /todo/list /todo/detail/* 時,這個子模塊里面的相關(guān)頁面就會展示,它也不會跟其他模塊有任何交互。也就是說,進入和離開這個子模塊,都是通過路由跳轉(zhuǎn)實現(xiàn)。這個子模塊也是完全獨立的,可以獨立開發(fā),也可以很容易就用到其他應用里面。

延時加載子模塊

下面,我們就可以通過修改路由的配置,使得todo模塊實現(xiàn)延時加載。Angular的路由模塊已經(jīng)提供了 loadChildren 定義可以直接幫我們實現(xiàn)該功能。下面就是新的app路由定義

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'todo', loadChildren: 'app/todo/todo.module#TodoModule' },
  { path: 'lazy', loadChildren: 'app/lazy/lazy.module#LazyModule' }
];

@NgModule({
 imports: [ RouterModule.forRoot(routes) ],
 exports: [ RouterModule ]
})
export classAppRoutingModule{ }

在這里,我們對于 todo 路徑,交給 app/todo/todo.module 里面的 TodoModule 模塊處理。而在 TodoModule 模塊里,已經(jīng)有一個子路由的定義。

最后,再修改 app.module.ts ,保證它里面不再引入 TodoModule 。如此一來,我們在主模塊AppModule里面,沒有引入 todo 模塊的任何組件或服務(wù)。這樣就能在完全脫離 TodoModule 模塊的情況下,運行主模塊的功能。當用戶打開 /todo 里面的url時,就加載 app/lazy/lazy.module 里面的 LazyModule 模塊,并交由它來處理響應的url。

總結(jié)一下,實現(xiàn)延時加載子模塊,主要是要注意下面幾點:

  1. 子模塊的路由用 RouterModule.forChild(TodoRoutes) 方式定義。
  2. 主模塊不要引入子模塊,也不要引入子模塊的任何組件或服務(wù),否則子模塊就會被打包進主模塊里。
  3. 只有子模塊才會用到的Service在子模塊的 providers 里面定義,如果是主模塊和子模塊都會用到的Service就用公用模塊的方式定義。要注意這個Service的實例只能有一個。

運行

接下來我們來看看運行的結(jié)果。(注意根據(jù)運行環(huán)境不同,文件大小會不一樣)

不啟用延時加載

首先,我們在 app.module.ts 引入 TodoModule ,這樣 todo 模塊不是延時加載的,只有 lazy 模塊是延時加載的。我們使用 ng serve 的方式運行測試服務(wù)器,并打開頁面,打開幾個頁面以后,網(wǎng)絡(luò)請求如下:

 

從圖中可以看到,有一個3.4M的main的js文件,下面的 1.chunk.js 的 lazy 模塊延時加載的。打包的文件確實是非常的大,因為lazy模塊非常簡單,只是顯示了一個字符串在模板里。所以它的大小也非常小,才5.8k。

延時加載模式

下面在把 TodoModule 模塊從 app.module.ts 去掉,這樣, todo 模塊就是延時加載的,再看一下網(wǎng)絡(luò)請求:

 

這下main文件變成了3.1M,lazy模塊對應的js文件是 1.chunk.js ,還是5.8k,todo模塊對應的文件 0.chunk.js 是324K??梢钥匆娨粋€很簡單的todo模塊,里面有service, rosolver, guards, 還有3個組件,里面分別都有模塊、css,雖然文件不少,但是他們的實現(xiàn)實際上都很小。只是一個模塊的文件,在未壓縮的情況下就有300多K,讓我這個Angular2的忠實粉絲都無語。

延時加載-prod模式

一般我們在部署應用的時候,都會使用壓縮、混淆、合并等方法來減少最終文件的大小。使用angular-cli工具,除了在編譯的時候提供打包的功能,甚至在測試的時候,也可以啟用壓縮選項。我們可以運行 ng serve -pro 來使用 prod 模式來啟動測試服務(wù)器。在啟動的過程中,可以看到很多類似下面的日志:

WARNING in 0.005fea95566fdabe23df.chunk.js from UglifyJs
Dropping unused function scheduleMicroTask [/Users/mavlarn/mydev/blog/angular2-tutorial/angular2-routes-lazy-module-webpack/~/@angular/forms/src/facade/lang.js:21,0]

可以看出,angular-cli的 prod 模式下編譯的時候,去除了很多不需要的代碼,這就是angular的 Tree Shaking 的功能。

運行以后,網(wǎng)絡(luò)請求如下:

 

這下main文件減少到了221K,lazy模塊對應的js文件是 1.chunk.js ,只有1.0k,todo模塊對應的文件 0.chunk.js 是17.9K??偣泊笮〈蟾攀?40K左右,如果再使用GZip壓縮,應該可以到6,70K左右。在官方文檔里提到,一個Angular2的簡單實例,通過Tree Shaking、壓縮、GZip,最終下載的包大小有50K。我們這個實例畢竟稍微復雜,實現(xiàn)了大多數(shù)的通用功能,如路由、guard、resolver、表單,也是用到了Rxjs里的 Observable ,所以最終壓縮后能有70K左右的話,也符合官方文檔的說法。

編譯后

最后,我們再使用 ng build --prod 來看看用prod模式編譯后的大小:

 

結(jié)果出乎意外,main文件的大小比上面在prod模式下運行測試服務(wù)器大很多,達到800多K。應該是編譯過程需要某些參數(shù),或者是當前的angular-cli有什么bug。

再使用 ng build --prod --aot 編譯,main文件的大小是446K。雖然小了一點,但是也不符合預期。

總結(jié)

先說延時加載,應該都知道可以減少第一次加載的文件的大小。特別是當某個模塊使用了一些比較大第三方的js庫,例如圖形庫等,那么,把這些模塊獨立出來,使用延時加載的方式,可以大大減少首次加載的時間。對于Angular2的應用來說,如果我們要定義 Component ,就從 @angular/core 里面引入 Component ,需要定義路由就從 @angular/router 里面引入`Router。所以,只要我們設(shè)計好了整個App的模塊、組件、路由,我們就可以利用延時加載的功能使得首頁文件盡可能的小。

使用模塊化的開發(fā),也能給我們的開發(fā)和維護帶來很大的便利,項目越大越大,模塊化和組件化帶來的便利就越明顯。

目前Angular2的天坑

在網(wǎng)上,經(jīng)??梢钥吹揭恍┪恼抡fAngular1或者2的一些坑。實際上,大部分都是因為使用不當,或者沒有按照最佳實踐去使用,特別是Angular1。雖然Angular1有本質(zhì)上的性能問題,但是,通過良好的整體設(shè)計、良好的 代碼規(guī)范和質(zhì)量,還是可以開發(fā)出很流暢的手機web應用。

但是,在準備這篇文章中的實例時,卻遇到了幾個嚴重的問題,讓我這個Angular2的忠實粉絲也很無奈。

Angular 2.2.2及以上版本的BUG

我在實例中使用的Angular的版本是2.2.1,如果用的版本是2.2.2 ~ 2.3.0之間,在運行或編譯的時候,可能會出現(xiàn)如下的錯誤:

ngCompiler.ReflectorHost is not a constructor
TypeError: ngCompiler.ReflectorHost is not a constructor

可以上Github查看該 issue 的情況。如果遇到這種問題,只能先使用2.2.1的版本。

Angular-Router

在這個實例中,延時加載的todo模塊里面有一個service,我們使用Angular的依賴注入的功能自動初始化以及諸如這個服務(wù)的實例。但是,在3.1.2及以上的版本里面,這個服務(wù)會被創(chuàng)建多次,每次激活相關(guān)路由的時候,就會創(chuàng)建一次。而且,只有在延時加載的模式才會發(fā)生這種錯誤。相關(guān) issue

TypeScript

在我之前的教程里,判斷用戶是否具有某種權(quán)限,使用了如下的方法:

hasRole(role: string): boolean {
  return this.account && this.account.roles.includes(role);
}

但是,更新了TypeScript以后,該方法就不存在了,原因可以查看 這個 .

所以改成了用 indexOf(role) > 0 來判斷列表里是否存在一個字符串。

雖然目前Angular還不是十分穩(wěn)定,有一些Bug,甚至TypeScript也不穩(wěn)定,但是,相信這些問題都能夠很快解決。而且隨著框架越來越成熟,也會越來越穩(wěn)定。

而且,Angular2+Typescript的開發(fā)方式也十分便利,Typescript的強類型檢查能夠幫助我們減少編碼的錯誤,提高效率。而且,我們也可以很方便的查看框架的API,能省去很多查資料的時間。

Angular2的很多思想非常適用于開發(fā)大型的應用。如果開發(fā)過大型的Java項目,就會發(fā)現(xiàn)學習Angular2是一件非常容易的事情。Angular2引入了很多面向?qū)ο蟮目蚣艿乃枷耄@些,都是在面向?qū)ο箢I(lǐng)域開發(fā)大型項目的多年開發(fā)經(jīng)驗。這些經(jīng)驗應用到前端開發(fā),也能幫助我們更方便的開發(fā)和維護大型的前端項目。

雖然,Angular2的應用最終的打包文件非常大(我們這個實例即使壓縮完后也有70K左右,但是如果用VUE的話會比這個小很多),但是隨著Angular2的越來越穩(wěn)定,各種開發(fā)工具越來越成熟,相信文件大小的問題也能夠有一個比較好的解決方案。因為Angular2的AOT、Tree Shaking的特性,為解決大小的問題提供了前提。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Angular組件生命周期(一)

    詳解Angular組件生命周期(一)

    每個Angular版本在其生命周期中都經(jīng)歷了各個階段。組件在Angular中起著關(guān)鍵作用; 在這里,本文將討論Angular中的組件生命周期以及它們?nèi)绾斡绊懣蚣芩邪姹镜纳芷凇?/div> 2021-05-05
  • 在 Angular 中使用Chart.js 和 ng2-charts的示例代碼

    在 Angular 中使用Chart.js 和 ng2-charts的示例代碼

    本篇文章主要介紹了在 Angular 中使用Chart.js 和 ng2-charts的示例代碼,具有一定的參考價值,有興趣的可以了解一下
    2017-08-08
  • Angular6 用戶自定義標簽開發(fā)的實現(xiàn)方法

    Angular6 用戶自定義標簽開發(fā)的實現(xiàn)方法

    這篇文章主要介紹了Angular6 用戶自定義標簽開發(fā)的實現(xiàn)方法,下面我們就通過一個簡單的例子演示Angular6中的這一新功能,小編覺得挺不錯的,現(xiàn)在分享給大家,需要的朋友可以參考下
    2019-01-01
  • Angular4的輸入屬性與輸出屬性實例詳解

    Angular4的輸入屬性與輸出屬性實例詳解

    這篇文章主要介紹了Angular4的輸入屬性與輸出屬性,結(jié)合實例形式詳細分析了Angular4輸入屬性與輸出屬性的概念、功能及相關(guān)使用技巧,需要的朋友可以參考下
    2017-11-11
  • AngularJS 實現(xiàn)JavaScript 動畫效果詳解

    AngularJS 實現(xiàn)JavaScript 動畫效果詳解

    本文主要介紹AngularJS 實現(xiàn) JavaScript 動畫的資料,這里整理了詳細的資料和簡單示例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • angularJS提交表單(form)

    angularJS提交表單(form)

    這篇文章主要介紹了angularJS提交表單(form)的方法和示例,需要的朋友可以參考下
    2015-02-02
  • 詳解AngularJS驗證、過濾器、指令

    詳解AngularJS驗證、過濾器、指令

    這篇文章主要介紹了AngularJS驗證、過濾器、指令的相關(guān)知識,angularJS中提供了許多的驗證指令,可以輕松的實現(xiàn)驗證,具體詳情大家通過本文一起學習吧,需要的朋友可以參考下
    2017-01-01
  • Angular2 PrimeNG分頁模塊學習

    Angular2 PrimeNG分頁模塊學習

    這篇文章主要為大家詳細介紹了Angular2 PrimeNG分頁模塊學習教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Angular ElementRef簡介及其使用

    Angular ElementRef簡介及其使用

    這篇文章主要介紹了Angular ElementRef簡介及其使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • 如何在Angular.JS中接收并下載PDF

    如何在Angular.JS中接收并下載PDF

    最近這兩天公司正在做一個PDF協(xié)議下載的功能,目前的解決方案可以分為完全前端生成和后端生成兩種方式。前端生成PDF有jsPDF 和pdfmake 兩種方式,下面這篇文章就給大家分享下如何在Angular.JS中接收并下載PDF的方法,有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-11-11

最新評論

堆龙德庆县| 墨江| 固安县| 清涧县| 荣昌县| 大化| 迭部县| 兰州市| 博湖县| 商丘市| 塔城市| 安徽省| 盐山县| 昌吉市| 江口县| 广灵县| 漳浦县| 延川县| 舒兰市| 济南市| 金昌市| 驻马店市| 资中县| 保康县| 贵州省| 新野县| 平南县| 安宁市| 贵定县| 镇远县| 安顺市| 全南县| 达日县| 满洲里市| 廊坊市| 扶绥县| 远安县| 竹山县| 皮山县| 西平县| 寿阳县|