1. 程式人生 > >使用Ionic3開發混合APP的架構設計總結

使用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的釋出。