第三课:登录页面和滑动菜单布局

这个应用中我们将要实现一个实际的普通页面工作流,具体讲就是,一个登录页引导至主应用。在大部分需要用户登录验证的应用中,都会首先显示验证屏幕,只有在用户登录成功之后才会来到主应用。
在我们这个应用中,我们会展示一个登录页,其中有一个使用Facebook登录的按钮,这个按钮会导向一个带有侧滑菜单布局的页面。咱们的登录页非常简单(至少目前是这样的)所以我们开始吧。
> 修改 src/pages/login/login.html为如下:

  1. <ion-content padding>
  2. <ion-row>
  3. <ion-col>
  4. <img src="assets/images/logo.png" />
  5. </ion-col>
  6. </ion-row>
  7. <ion-row>
  8. <ion-col>
  9. <p>Camper Chat allows you to talk to other <strong>caravaners,
  10. RV'ers, roadtrippers and campers</strong> near you. Use
  11. Camper Chat to give and receive tips, ask for help with your
  12. flat tyre, or just have a friendly chat.</p>
  13. <p>Log in with <strong>Facebook</strong> below to get started.</p>
  14. </ion-col>
  15. </ion-row>
  16. <ion-row>
  17. <ion-col>
  18. <a (click)="login()"><img src="assets/images/facebook-button.png"/></a>
  19. </ion-col>
  20. </ion-row>
  21. </ion-content>

这样就定义好了我们的登录页模板,如果这不是你制作的第一个Ionic 2应用的话(我当然也希望不是),你会注意到,我没有在模板中加入navbar。我们不需要显示标题,不需要显示返回按钮,或者类似的东西,所以不用navabar是相当正确的。
我们这里没做啥疯狂的事情,我们在这里用到了Ionic的栅格系统,也就是行与列来设置我们的布局。当使用格子系统的的时候,行都是上下排列,行中的列是左右排列的。下面这个图标可以帮你很好的说明:
栅格系统

这是个很简单的用力,因为我们只是使用格子来上下排列展示三个不同的部分,你可以在行中间插入多列甚至可以定义每个列的宽度:

  1. <ion-row>
  2. <ion-col width-10></ion-col>
  3. <ion-col width-50></ion-col>
  4. </ion-row>

同时我们也给Facebook登录图片添加了一个(click)处理器。这个login函数实际上是触发使用Facebook进行验证,但是目前我们只是将要触发一个页面切换到主页以便完成我们的布局设置。我们现在来设置他的类以便设置好页面切换。
> 修改 src/pages/login/login.ts为如下:

  1. import { Component } from '@angular/core';
  2. import { Platform, NavController, MenuController, AlertController } from 'ionic-angular';
  3. import { Facebook } from 'ionic-native';
  4. import { HomePage } from '../home/home';
  5. import { Data } from '../../providers/data';
  6. @Component({
  7. selector: 'page-login',
  8. templateUrl: 'login.html'
  9. })
  10. export class LoginPage {
  11. constructor(public nav: NavController, public platform: Platform, public menu: MenuController, public dataService: Data, public alertCtrl:AlertController) {
  12. this.menu.enable(false);
  13. }
  14. login(): void {
  15. this.getProfile();
  16. }
  17. getProfile(): void {
  18. this.menu.enable(true);
  19. this.nav.setRoot(HomePage);
  20. }
  21. }

可以看到,上面代码中,我们注入并设置好了NavController我们在调用login函数的时候用它来将rootPage设置为HomePage。这些代码都是通过getProfile()运行的,因为我们稍后会在用户通过Facebook认证后获取回去一些信息,但是在我们把用户发配到下一页之前,由于我们还没有实现这个功能,所以我们只是让代码把我们带到成功的场景。
MenuController用于与即将添加的侧滑菜单交互。稍后会详细讨论这个,但是我们不想这个菜单中登录页是展示,所以我们使用了菜单的enable函数在此页面上禁用此菜单。我们在切换到Home也之后我们再次启用他。
我们也从Ionic Native导入了Facebook插件,稍有将会是一。记住,使用一个Cordova插件不需要导入任何东西,甚至是Facebook插件,但是,如果你是通过Ionive Native使用的话那么你就得去导入他了。
我们想要登录页第一个展示,但是如果此时你看app.module.ts的时候,会发现当前默认的根页面是主页:

  1. rootPage: any = HomePage;

所以,我们当然得修改一下。
> 修改 src/app/app.component.ts为如下:

  1. import { Component, ViewChild } from "@angular/core";
  2. import { Facebook } from 'ionic-native';
  3. import { Nav, Platform, MenuController } from 'ionic-angular';
  4. import { StatusBar } from 'ionic-native';
  5. import { HomePage } from '../pages/home/home';
  6. import { AboutPage } from '../pages/about/about';
  7. import { LoginPage } from '../pages/login/login';
  8. import { Data } from '../providers/data';
  9. @Component({
  10. templateUrl: 'app.html'
  11. })
  12. export class MyApp {
  13. @ViewChild(Nav) nav: Nav;
  14. rootPage: any = LoginPage;
  15. homePage: any = HomePage;
  16. aboutPage: any = AboutPage;
  17. constructor(public platform: Platform, public dataService: Data, public menu: MenuController) {
  18. platform.ready().then(() => {
  19. });
  20. }
  21. openPage(page): void {
  22. }
  23. logout(): void {
  24. }
  25. }

你也看到了,我们把根页设为了登录页,当然我们也得先导入Login也。我们现在也做了不少东西了。我们导入一个设置了Data provider的引用,我们后续会用他来保存和访问数据;Menu Controller,允许我们和创建中的侧滑菜单交互。同时,我们也用到了@ViewChild,他允许我们获取我们的Nav组件(下一步将会添加的)的直接引用。这很有必要因为我们不能在跟组件里面使用NavController,但是我们后续需要在这里改变rootPage所以我们直接获取Nav
我们这里设置了一些函数,稍后会完成他们的定义。openPage函数将处理侧滑菜单(将在这里设置与homePageaboutPage变量绑定)不同选择之间的切换,logout函数将用于登出当前应用。我们已经从Ionic Native中导入了Facebook插件,所以logout函数将与Facebook API交互。
同时,我们在装饰器里面用到了templateUrl连接到了一个app.html文件。大部分情况下我们都不需要担心根组件的独立模板文件,因为他太简单了(通常只是nav)。由于我们用来一个侧滑菜单,所以我们得自己去模板中定义这个菜单了,由于跟之前比有点多。所以我们现在来做这个。
> 在 app 文件夹内创建一个文件名为 app.html

  1. <ion-menu [content]="content">
  2. <ion-content>
  3. <ion-list no-lines>
  4. <button ion-item (click)="openPage(homePage)">
  5. <ion-icon name="chatbubbles"></ion-icon> Chat
  6. </button>
  7. <button ion-item (click)="openPage(aboutPage)">
  8. <ion-icon name="information-circle"></ion-icon> About
  9. </button>
  10. <button ion-item (click)="logout()">
  11. <ion-icon name="power"></ion-icon> Logout
  12. </button>
  13. </ion-list>
  14. </ion-content>
  15. </ion-menu>
  16. <ion-nav id="nav" #content [root]="rootPage"></ion-nav>

这里有些比较有趣的东西。着部分代码可能你看起来比较眼熟:

  1. <ion-nav id="nav" #content [root]="rootPage"></ion-nav>

只有点点例外,也就是#content# 语法用于在模板定义本地变量,所以我们这里做的就是将指派给本地变量content。然后我们在我们的中使用这个变量来正确的设置他的内容:

  1. <ion-menu [content]="content">

所以我们这里做的实际上就是告诉菜单他本身需要附加的内容是啥,在本例中也就是我们的整个应用。里面的其他内容只是菜单将要包含的内容,我们所作的知识创建一个按钮列表用作标签栏作用给用户点击。每个标签栏都会调用我们在根组件中定义的函数。
布局拼图的最后一篇是创建主页,我们先从模板入手。
> 修改 src/pages/home/home.html为如下:

  1. <ion-header>
  2. <ion-navbar color="primary">
  3. <button ion-button icon-only menuToggle>
  4. <ion-icon name="menu"></ion-icon>
  5. </button>
  6. <ion-title>
  7. <img src = "assets/images/logo.png" class="logo" />
  8. </ion-title>
  9. </ion-navbar>
  10. </ion-header>
  11. <ion-content class="home" #chat id="chat">
  12. <ion-list no-lines>
  13. <ion-item>
  14. <ion-avatar item-left>
  15. <img src="">
  16. </ion-avatar>
  17. <h2>Name here</h2>
  18. <p>message here</p>
  19. </ion-item>
  20. </ion-list>
  21. </ion-content>
  22. <ion-footer>
  23. <ion-toolbar>
  24. <ion-input [(ngModel)]="chatMessage" type="text" placeholder="enter message..."></ion-input>
  25. <button ion-button icon-only (click)="sendMessage()" style="position:absolute; right: 0; top: 0; margin: 0;">
  26. <ion-icon name="chatbubbles"></ion-icon>
  27. </button>
  28. </ion-toolbar>
  29. </ion-footer>

我们在这个模板中重新用到了navbar,我们添加了一个按钮并给这个按钮添加了menuToggle属性这个属性将会添加一个按钮让用户可以切换菜单的开关(菜单可以通过划入和划出来打开和关闭,这就是为什么我们需要在登录页禁用他甚至我们都不添加一个菜单按钮)。
同时,请注意我们使用“#chat”定义了一个本地变量,也就是,这是因为我们稍有会通过@ViewChild来获取他的引用,我之前说过我们用作导航组件。
在内容区域里,我们创建了一个列表,目前其中只有一个(后续我们会用*ngFor来展示所有信息),我们也用到了我们可以通过他给图片添加一些不错的样式。实际上我们将会在此处添加贴出信息的用户的名字,以及信息。
我们也用到了一个,他相当于一个缩减了所有导航魔法的navabar。这是一个我们可以添加标题,按钮或者其他东西的条,在本例中,我们将它放到屏幕底部,而不是顶部。这样我们可以保有一个信息输入区域即使在列表滚动的情况下他都死死的抱紧屏幕底部。
在toolbar里面我们加入了一个输入框,并通过[(ngModel)]将他与charMessage进行双向数据绑定。这就意味着当他的值变化的时候,homt.ts里面对应的this.chatMessage(稍后创建)也会改变(反之亦然)。然后我们就添加了一个按钮用于发送输入的信息,我们添加了一些内置样式让他浮在toolbar的右边。
现在来创建类定义,我们的home.ts文件。
> 修改 src/page/home/home.ts 为如下:

  1. import { Component } from '@angular/core';
  2. import { Data } from '../../providers/data';
  3. @Component({
  4. selector: 'page-home',
  5. templateUrl: 'home.html'
  6. })
  7. export class HomePage {
  8. chatMessage: string = '';
  9. messages: any = [];
  10. constructor(public dataService: Data){
  11. }
  12. sendMessage(): void {
  13. }
  14. }

这里蛮简单的,我们再次导入和注入了Data服务。我们设置好了模板内已经进行双向绑定的this.chatMessage和一个空的信息数组用来存储展示到屏幕的信息。
此时,运行应用的时候:

  1. ionic serve

可以查看两个页面,大概是这样的:
主页
登录页
不出意料,看起来还是蛮丑的,但是我们需要的基础布局已经摆在那里了。我们有一个带有登录选项的登录页,将会把我们引导至一个带有侧滑菜单的主页。
下节课我们将开始整合Facebook API这样我们可以让用户真正的登录(同时他可以给我们提供一些会在应用中用到的数据,像是用户名啦,用户头像啦)。