第七课:重用组件

听说你喜欢app,那么我就在你的app里面放一个app好了。目前为止我们的应用有三个标签页了,我们现在要加个全新的标签页了。我们本书的第一个应用QuickList跟咱们应用很搭调呢。外出露营的时候Checklist非常方便的说。
我们这节课要做的是基上就是将Quick List功能“拖放”到当前应用中。在Ionic 2和Angular 2 的模块化的天性之下,这些事情可以很轻易的实现。如果你之前已经创建好了Quick List的话,你只要去其中拷贝代码即可,如果没有的话,那么去下载的包里拷贝代码。
没有像“拖放”那么容易,因为直接拖放的话会有一些冲突,但是还是很直白。我们先从文件拷贝开始。
> 拷贝 QuickList 的 models 文件夹到 CamperMate 的 src 文件夹中
> 拷贝 QuickLists 的 checklist 页文件夹到 CamperMate的 pages 文件夹
这两部非常简单,但是现在我们会遇上一点小问题。我们也想要从QuickLists中拷贝HomePage,但是我们的CamperMate已经有HomePage了,所以我们需要做一点点变通。
> 在CamperMate 的 pages 文件夹内创建一个新的文件夹名为 quicklistshome
> 将 QuickLists 的 home文件夹里面的内容(home.ts,home.scss,home.html)拷贝到刚才新建的 quicklistshome 里面
> 将 home.ts,home.scss,home.html重命名为quicklistshome.ts,quicklistshome.scss, quicklistshome.html
现在得到的结果是我们从QuickLists中将他的整个home页都拷贝过来了,但是拷贝过来之后我们都重命名为quicklistshome,因为我们不想让他和已有的home页有冲突。如果对上面的内容感觉比较迷惑,那么请查看本书源代码的文件夹结构。
由于我们对文件名进行了变更,我们也需要对代码进行一些变动。我们需要将QuickLists Home Page的类名,同时我们也要修改模板的名字:
> 对 src/pages/quicklistshome/quicklistshome.ts 进行如下变更:

  1. import { Component } from '@angular/core';
  2. import { NavController, AlertController, Platform } from 'ionic-angular';
  3. import { ChecklistPage } from '../checklist/checklist';
  4. import { ChecklistModel } from '../../models/checklist-model';
  5. import { Keyboard } from 'ionic-native';
  6. import { Data } from '../../providers/data';
  7. @Component({
  8. selector: 'page-quicklistshome',
  9. templateUrl: 'quicklistshome.html'
  10. })
  11. export class QuickListsHomePage {
  12. checklists: ChecklistModel[] = [];
  13. local: Storage;
  14. constructor(public nav: NavController, public platform: Platform, public dataService: Data, public alertCtrl: AlertController) {
  15. }
  16. ionViewDidLoad(){
  17. this.platform.ready().then(() => {
  18. this.dataService.getData().then((checklists) => {
  19. let savedChecklists: any = false;
  20. if(checklists && typeof(checklists) != "undefined"){
  21. savedChecklists = JSON.parse(checklists);
  22. }
  23. if(savedChecklists){
  24. savedChecklists.forEach((savedChecklist) => {
  25. let loadChecklist = new ChecklistModel(savedChecklist.title, savedChecklist.items);
  26. this.checklists.push(loadChecklist);
  27. loadChecklist.checklist.subscribe(update => {
  28. this.save();
  29. });
  30. });
  31. }
  32. });
  33. });
  34. }
  35. }

注意类型和templateUrl都变了。有一个我们忽略了的事情是我们没有将Quicklists应用的Data服务拷贝过来。这个因为我们的CamperMate应用已经有一个了,所以我们只要对他进行改动就可以了。
> 给 src/providers/data.ts 添加下面两个函数:

  1. getData(): Promise<any> {
  2. return this.storage.get('checklists');
  3. }
  4. save(data: any): void {
  5. let saveData = [];
  6. //Remove observables
  7. data.forEach((checklist) => {
  8. saveData.push({
  9. title: checklist.title,
  10. items: checklist.items
  11. });
  12. });
  13. let newData = JSON.stringify(saveData);
  14. this.storage.set('checklists', newData);
  15. }

这两个函数的命名方式和data.ts里面其他函数的命名方式不一样,保持这样的原因是避免对Quicklists功能做更多的修改。
样式方面没有多少要做的,但是我们的Quicklists应用的navbar都是用的secondary颜色,但是CamperMate用的是primary,所以我们需要对它进行改动。
> 修改 src/pages/checklist/checklist.html 的navbar为如下:

  1. <ion-navbar color="primary">

> 修改 src/pages/quicklistshome/quicklistshome.html 的navbar为如下:

  1. <ion-navbar color="primary">

> 修改 src/pages/quicklistshome/quicklistshome.scss 为如下:

  1. page-quicklistshome {
  2. ion-item-sliding {
  3. margin: 5px;
  4. }
  5. .home-item {
  6. font-size: 1.2em;
  7. font-weight: bold;
  8. color: #282828;
  9. padding-top: 10px;
  10. padding-bottom: 10px;
  11. }
  12. .secondary-detail {
  13. display: block;
  14. color: #cecece;
  15. font-weight: 400;
  16. margin-top: 10px;
  17. }
  18. }
  19. button {
  20. border: none !important;
  21. }

这样一来,我们就在CamperMate应用里面完美移植了QuickLists功能了。我们现在只要加上对于的标签栏就可以了。
> 修改 src/pages/home/home.html以包含下面第四个标签栏

  1. <ion-tabs>
  2. <ion-tab [root]="tab1Root" tabTitle="Location" tabIcon="navigate"></ion-tab>
  3. <ion-tab [root]="tab2Root" tabTitle="My Details" tabIcon="person"></ion-tab>
  4. <ion-tab [root]="tab3Root" tabTitle="Camp Details" tabIcon="bookmarks"></ion-tab>
  5. <ion-tab [root]="tab4Root" tabTitle="Checklists" tabIcon="checkbox"></ion-tab>
  6. </ion-tabs>

这样我们就可以去类定义中定义tab4Root了。
> 修改 src/pages/home/home.ts到如下:

  1. import { Component } from '@angular/core';
  2. import { LocationPage } from '../location/location';
  3. import { MyDetailsPage } from '../my-details/my-details';
  4. import { CampDetailsPage } from '../camp-details/camp-details';
  5. import { QuickListsHomePage } from '../quicklistshome/quicklistshome';
  6. @Component({
  7. selector: 'page-home',
  8. templateUrl: 'home.html'
  9. })
  10. export class HomePage {
  11. tab1Root: any = LocationPage;
  12. tab2Root: any = MyDetailsPage;
  13. tab3Root: any = CampDetailsPage;
  14. tab4Root: any = QuickListsHomePage;
  15. constructor(){
  16. }
  17. }

新加的页面也需要去app.module.ts中进行导入。
> 修改src/app/app.module.ts 为如下:

  1. import { NgModule } from '@angular/core';
  2. import { IonicApp, IonicModule } from 'ionic-angular';
  3. import { MyApp } from './app.component';
  4. import { Storage } from '@ionic/storage';
  5. import { HomePage } from '../pages/home/home';
  6. import { LocationPage } from '../pages/location/location';
  7. import { MyDetailsPage } from '../pages/my-details/my-details';
  8. import { CampDetailsPage } from '../pages/camp-details/camp-details';
  9. import { QuickListsHomePage } from '../pages/quicklistshome/quicklistshome';
  10. import { ChecklistPage } from '../pages/checklist/checklist';
  11. import { GoogleMaps } from '../providers/google-maps';
  12. import { Connectivity } from '../providers/connectivity';
  13. import { Data } from '../providers/data';
  14. @NgModule({
  15. declarations: [
  16. MyApp,
  17. HomePage,
  18. LocationPage,
  19. MyDetailsPage,
  20. CampDetailsPage,
  21. QuickListsHomePage,
  22. ChecklistPage
  23. ],
  24. imports: [
  25. IonicModule.forRoot(MyApp)
  26. ],
  27. bootstrap: [IonicApp],
  28. entryComponents: [
  29. MyApp,
  30. HomePage,
  31. LocationPage,
  32. MyDetailsPage,
  33. CampDetailsPage,
  34. QuickListsHomePage,
  35. ChecklistPage
  36. ],
  37. providers: [Storage, Data, GoogleMaps, Connectivity]
  38. })
  39. export class AppModule {}

现在加载应用的话,应该可以看到一个新的标签页:
标签页

如你所见,这样模组是项目结构使得重用其他应用中的代码非常简单,如果用同名组件的话就会更简单了。
我们的应用现在看起来已经很好了,但是下节课我们要加入一点样式让他更好看些。