使用Ionic3開發混合APP的架構設計總結
Ionic在2017年3月7號在其官方部落格宣佈 Ionic3 正式版本釋出,採用最新的Angular4,和以往一樣的scss,Ionic3和2版本的主要區別就是對懶載入的全面使用。在使用Ionic2的時候,如果應用比較大,將所有的component,directives,pipes,services通通塞到app.module.ts裡面,總會讓我們感到不太雅觀,也不便於程式碼管理維護,同時在開啟應用的時候必然造成等待時間過長,3版本釋出,就是為了解決這些問題,它也確實解決了一些問題,但是Ionic3絕不是完美的,它也帶來了一些尷尬的問題。
一)懶載入
Ionic3預設採用懶載入機制,什麼是懶載入呢?當我們第一次進入應用,會載入app.module,如果沒有采用懶載入,那麼app.module裡的所有東西都會被載入,很顯然這是不太合適的,因為裡面的元件和服務我們在第一次進入應用時並沒有全部使用,可能只使用了很少的一部分,那麼對於比較大型的應用來說,由於頁面和其他的服務,指令,管道比較多,就會造成比較使用者體驗不好的影響。
這個時候我們需要把應用分為一個個module,各自引入自己用到的東西,不要管別的模組。那麼第一次進入應用,就只加載很少的app.module和root page對應的module,當我們進入其他頁面的時候,才會去載入相應的module。這樣的好處是專案程式碼結構清晰,易於維護,易於開發,而且第一次載入速度比較快。
當我們使用Ionic3的CLI來新建頁面,預設的會是懶載入的結構,甚至不止頁面,所有的component,service,directive都預設的是懶載入。
Ionic3採用IonicPage()和IonicPageModule引入了一個新的概念——page,我們通過CLI新建的Page可以通過很簡單的方式來跳轉:
this.navCtrl.push('DeviceListPage', {marker: deviceSourceData});
- 1
不需要像Ionic2那樣引入元件,只需要使用引號,裡面寫上頁面名字,就可以實現跳轉,這是因為IonicPageModule將這個頁面Module宣告過了:
IonicPageModule.forChild(DeviceListPage),
- 1
二)動態載入元件
這樣的確是簡化了頁面跳轉的工作,但是當我們想跳轉到某個元件,或者使用某個元件呢?比如說使用ModalController或者PopoversController,我們知道在Ionic2需要傳入元件,在當前頁面引入Modal Component之後:
let modal = this.modalCtrl.create(GuideFileListModalComponent);
modal.present();
- 1
- 2
但是在Ionic3裡面如果我們想要在某個module裡面這樣使用,需要將使用這個元件的Module在app.module.ts裡import,然後將Modal Component放到當前module裡宣告然後引入進entryComponents。
@NgModule({
declarations: [
SelectionGuidePage,SearchSelectionGuideModalComponent,GuideFileListModalComponent
],
imports: [
IonicPageModule.forChild(SelectionGuidePage),
FootTabBarComponentModule,
SharedLazyModule,
AccordionModule
],
entryComponents:[SelectionGuidePage,SearchSelectionGuideModalComponent,GuideFileListModalComponent],
exports: [
SelectionGuidePage
],
})
export class SelectionGuidePageModule {}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
以上程式碼裡的SearchSelectionGuideModalComponent和GuideFileListModalComponent是我需要動態載入的元件,SelectionGuidePageModule是引用他們的module,這裡的SelectionGuidePageModule就需要在app.module裡面import,同時我們注意到這裡SelectionGuidePage是進行動態載入modal的component,也在entryComponents列表裡面。
另外一種進行動態載入元件的更加簡單的方式是將你的Modal Component使用IonicPage裝飾器,將這個Component推入page棧裡。受益於Ionic3提供的便利之處,不需要在當前頁面引入Modal Component,直接使用動態元件的名稱字串作為引數傳入即可。
let modal = this.modalCtrl.create('GuideFileListModalComponent');
modal.present();
- 1
- 2
可以想象,如果我們想要在Ionic3裡面像一般的Angular2 Web 應用那樣在module裡面配置自己的路由機制,或者想給一個頁面設定子頁面,就像Angular2裡的路由children屬性,是比較困難的,Ionic官博說Ionic4會主要解決這樣的頁面之間的路由問題。
當然,還有另外一種場景下,使用懶載入的方式載入元件是很好的,就是隻在模板html裡面使用元件,並不是動態新增進來,比如有一個Page,裡面的內容比較多,我把它寫成了很多元件,每個元件有自己的Input和Output:
<div class="device-detail-monitor-content">
<device-detail-monitor *ngSwitchCase="'device-monitor'" [theDeviceData]="deviceMonitorData"></device-detail-monitor>
</div>
<div class="device-detail-time-content">
<device-detail-time *ngSwitchCase="'device-time'"
[ChartData]="timePieSingleChart"
[TimeLineChart]="timeLineChart"
[TimeInterval]="timeAnalysisInterval"
(selectTimeInterval)="changeTimeAnalysisInterval($event)"
></device-detail-time>
</div>
<div class="device-detail-production-content">
<device-detail-production *ngSwitchCase="'device-production'"
[ChartData]="productionLineChart.Data"
[ChartOptions]="productionLineChart.Options"
[TimeInterval]="timeAnalysisInterval"
(selectProductionInterval)="changeProductionAnalysisInterval($event)"
></device-detail-production>
</div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
這些元件都有各自的module,因此我在這個頁面把他們全都引入就可以了:
import {DeviceDetailMonitorComponentModule,
DeviceDetailTimeComponentModule,
DeviceDetailProductionComponentModule,
FootTabBarComponentModule} from '../../components/index';
- 1
- 2
- 3
- 4
Ionic3這種懶載入機制會帶來一個問題,就是所有的頁面在第一次進來沒有載入,只有在你點選進入某個頁面,它的module才會載入,這個過程會有幾秒鐘的時間(載入自己module的過程),在瀏覽器上測試的時候沒有這個問題(可能計算機的處理速度比手機要快),在真機上會給人一種我點選了之後沒有反應的感覺,使用者體驗不好。這個問題的解決辦法就是:把這些需要第一次進來就載入的module在app.module裡面import進來。
三)外掛
另外和2相比,使用cordova外掛的方式也有所變化,不再是一次性安裝,而是使用哪個安裝哪個,比如:
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import {Device} from '@ionic-native/device';
import {AppAvailability} from '@ionic-native/app-availability';
- 1
- 2
- 3
- 4
而且在3裡面他們全都成了服務,你還需要在app.module的providers屬性宣告一下:
providers: [
StatusBar,SplashScreen,Device, AppAvailability, Transfer, File,FileOpener,
{provide: ErrorHandler, useClass: IonicErrorHandler}
]
- 1
- 2
- 3
- 4
此外,在你更新ionic cli的版本之後,還需要更新ionic cordova cli和ionic plugin cli,在build和run的過程上沒有太大變化,不過所有的命令列都從以前的ionic XXXX變為了ionic cordova XXXX,可能cordova對ionic對他們的宣傳不足有意見吧。
在開發過程中,國內基本沒有Ionic3的資料,連Ionic2都比較少,因此查問題,找解決辦法,推薦使用英文搜尋,Ionic官方論壇的帖子,還有ionic team github上的issue,還有官方部落格,釋出的頻率比較低,不過每一篇都是精品,必須仔細研讀。
總的來說,Ionic3還是比2進步的,只不過有些新帶來的問題還要解決才能更好,期待Ionic4的釋出。