# -- 第六课：模块

模板，个人认为是Ionic 2中最有趣的东西。也是框架能力闪耀的地方。看看下面的代码：

```markup
<ion-header>
    <ion-navbar color="secondary">
        <ion-title>
            My Friends
        </ion-title>
        <ion-buttons end>
        <button ion-button icon-only (click)="doSomethingCool()"><ion-icon name="add-circle"></ion-icon></button>
        </ion-buttons>
    </ion-navbar>
</ion-header>
<ion-content>
    <ion-searchbar (input)="getItems($event)"></ion-searchbar>
    <ion-list>
        <ion-item *ngFor="let item of items">
            <ion-avatar item-left>
            <img [src]="item.picture">
            </ion-avatar>
            <h2>{{item.name}}</h2>
            <p>{{item.description}}</p>
        </ion-item>
    </ion-list>
</ion-content>
```

上面代码在没有额外样式的情况下，看起来将会是这样的： ![列表](https://877130497-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LBtuaet5GRr7L6p_j6_%2F-LBty0R2-90Yy_bs85eB%2F-LBty3HCwQlQImtkIhdl%2F1.6.1.jpg?generation=1525685968364554\&alt=media)

看起来没那么惊艳，但是我们就已经用简单的几行代码设置好了一个复杂的布局，加点自定义样式的话，我们就可以得到一个非常时尚的界面了。稍后我们会从各个方面彻底的了解在Ionic 2中创建模板，但是目前我需要给你找找一个完整的页面模板看起来是什么感觉，以及使用Ionic提供的组件是多么的简单。

Ionic 2中的模板语法有很多知识需要学习，如果你之前有使用过Ionic 1的话，你会发现他有一些重大的变更 —— 所以我们需要具体的学习一下模板。

此后也会涉及到其他的一些知识，但是这个是我认为这开始使用Ionic 2之前最后学要学习的‘核心’知识 —— 一旦你拿下了类和模板，那么你就可以直接可以开始制作一些东西。所以，我们先转入一些基础理论知识的学习，然后在做学一些练习示例吧。

## \* 语法

\*可能是Ionic 2里面最让人困惑的语法之一了。你会经常遇到一些这样的代码：

```markup
<ion-item *ngFor="let item of items">
```

或者

```markup
<p *ngIf="someBoolean"><p>
```

诸如此类。在Angular 2中 *语法用与创建一个嵌入模板的快捷方式，所以，当我们使用* ngIf的时候，上面的代码展开来就是：

```markup
<template [ngIf]="someBoolean">
    <p></p>
</template>
```

使用模板的原因是Angular 2将模板看作是DOM块，这样一来就可以动态操作他了。所以，在上面的 \*ngIf 范例中我们不会只按照字面意思将他渲染到DOM，

```markup
<p *ngIf="someBoolean"></p>
```

如果 *someBoolean* 等于true的话，会显示：

```markup
<p></p>
```

false的话就不显示。同理，当我们使用 \*ngFor的时候，我们不只是按照字面上去渲染：

```markup
<p *ngFor="let item of items">{{item.name}}</p>
```

我们会针对每个条目分别以段落的方式渲染出来：

```markup
<p>Bananas</p>
<p>More Bananas</p>
<p>Pancakes</p>
```

要使用这个功能的话，我们需要使用，但是手动写这些模板又很繁琐，所以 *语法是用来简化这些繁琐的操作的。*\
*解释得这么清楚了，我们来具体的看看想* ngIf 和 \*ngFor 这样的指令的使用方法。

## 循环

很多时候你会循环大量的数据 —— 例如当你有一个文章列表你想要将所有文章的标题渲染到一个列表。我们就可以用Angular 2 提供的**ngFor**指令来完成这个任务了 -- 看起来大概是这样的：

```markup
<ion-list>
    <ion-item *ngFor="let article of articles" (click)="viewArticle(article)">
        {{article.title}}
    </ion-item>
</ion-list>
```

上面的例子中，我们创建了一个，然后对于**articles**数组里面的每个**article**我们都添加了一个。在之前的基础部分我讲过了使用let来创建一个局部变量，我们这里就用到了。他允许我们访问我们当前循环到的**article**，我们使用这个变量来获取他的标题然后在列表上渲染出来，同时，在用户点击的时候将他传入到*viewArticle*函数中。\
通过将当前article的引用传入到*viewArticle*函数，我们可以用来做类似弹出文章新页面的操作。

## 条件

有时候你想着符合特定条件的情况下展示模板特定的部分，可以使用一些方法来做到：

```markup
<div *ngIf="someBoolean">
```

当*ngIf*的表达式值为true的时候，那么他附加到的节点才会被渲染出来。在本例中，只有在*someBoolean*为true的时候，才会被添加到DOM，反之则不会。\
\&#xNAN;*ngIf*在布尔场景（true和false）下非常厉害，但是有时候你需要根据大量不同的值来处理。这种情况下就得使用*ngSwitch*：

```markup
<div [ngSwitch]="paragraphNumber">
    <p *ngSwitchCase="1">Paragraph 1</p>
    <p *ngSwitchCase="2">Paragraph 2</p>
    <p *ngSwitchCase="3">Paragraph 3</p>
    <p *ngSwitchDefault>Paragraph</p>
</div>
```

在这个例子中，我们使用*ngSwitch*来检查*paragraphNumber*的值。哪个*ngSwitchCase*语句匹配到了这个值，就会是以哪个作为DOM元素去渲染，如果没有匹配上的值，那么就用*ngSwitchDefault*元素。\
还可以通过*hidden*属性去根据条件去显示或者隐藏一个元素。\
例如：

```markup
<ion-avatar [hidden]="hideAvatar" item-left>
```

在这个例子中，当*hideAvatar*为**true**的时候，这个元素将会隐藏，当为**false**的时候则显示。使用这个方法的时候，你的类定义里面应该有**this**.*hideAvatar*变量存在，你可以通过给这个变量赋值来控制元素的显示和隐藏。\
不但可以根据条件显示整个元素，还可以根据条件给元素添加不同的类，例如：

```markup
<ion-avatar [class.my-class]="showMyClass" item-left>
```

这个跟上面&#x7684;*\[hidden]*&#x65B9;法类似，但是他不是根据条件显示和隐藏元素，他根据条件来添加CSS里面定义好的类。这个方法非常实用，例如，当你想要用来区分列表里面已读和未读信息的时候。

## Ionic 2 模板组件

目前为止谈到的基本上都是Angular 2的东西，没有Ionic特有的（除了模板里用的和之外）。这些语法和一些Ionic特有组件将在你的模板里贯穿始终。我们现在要学习一些Ionic特有的东西了，先从Ionic 2页面模板的基本布局开始：

```markup
<ion-header>
    <ion-navbar>
        <ion-title>
            Home
        </ion-title>
    </ion-navbar>
</ion-header>

<ion-content class="home">
    <ion-card>
        <ion-card-header>
            Card Header
        </ion-card-header>
        <ion-card-content>
            Hello World
        </ion-card-content>
    </ion-card>
</ion-content>
```

这个是你使用blank布局自动生成的模板代码。这里有两个很重要的组件，基本每个模板都会出现的：和。\
元素只是简单的用来包含页面的主要内容（本案例中的‘卡片’），并允许滚动。注意，他有个名为‘home’的类，如果你查看**home.scss**文件的时候，你会发现里面有‘home’的类定义。他没做什么特别的事情，他只是一个约定，允许你对的样式单独进行变更（记住，即使你只是在**home.scss**里添加了样式，这样新样式还是会应用到整个项目的，文件分离只是为了架构而已）。\
两者之间更为有趣的是。这个是用来添加页首的，里面可以添加页标题，以及左右按钮。虽然这可以不大符合审美，他还有很多内置的导航智能。如果你是**压入 push**一个新页面（后面会涉及），那么里面会自动出现一个返回按钮允许用户返回之前页面，而不用你手动去添加。\
上面部分包含的基本模板语法在Ionic 2页面中会经常见到，其他需要做的就是拖入和配置Ionic 2提供的大量组件（如果你喜欢冒险，那么自建组件）。\
现在我们看一下如何在模板中实现一些Ionic组件。我们不会全部组件都讲到，因为它们是在是太多了，我们只是来尝尝鲜。完整的组件列表，可以在[Ionic 2文档](http://ionicframework.com/docs/components/#overview)中查阅。

### 列表 List

列表上移动应用中使用最广泛的组件之一，他们提佛那个一个很有趣的挑战。在本地应用上滑动那种丝滑的感觉，那种顺滑的加速和减速，感觉起来真的是爽呆了 -- 这种感觉很难复制。幸运的是，你不用担心这个，Ionic 2为了解决了所有的难点，下面这样就可以简单地使用列表了：

```markup
<ion-list>
    <ion-item>Item 1</ion-item>
    <ion-item>Item 2</ion-item>
    <ion-item>Item 3</ion-item>
</ion-list>
```

或者如果你想要根据类定义里面的一系列数据来动态窗台你的列表：

```markup
<ion-list>
    <ion-item *ngFor="let item of items" (click)="itemSelected(item)">
        {{item.title}}
    </ion-item>
</ion-list>
```

### 滑块 Slide

滑块是另一个移动应用的通用组件之一，滑块看起来是这样的： ![滑块](https://877130497-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LBtuaet5GRr7L6p_j6_%2F-LBty0R2-90Yy_bs85eB%2F-LBty3y0WwKb07RB3iiU%2F1.6.2.jpg?generation=1525685968374103\&alt=media)\
在你有大量的图片或者页面想要通过用户左右滑动来展示的情况下，滑块就可以上场了。与列表一样，使用滑块也非常简单：

```markup
<ion-slides [options]="slideOptions">
    <ion-slide>
        <h2>Slide 1</h2>
    </ion-slide>

    <ion-slide>
        <h2>Slide 2</h2>
    </ion-slide>

    <ion-slide>
        <h2>Slide 3</h2>
    </ion-slide>
</ion-slides>
```

这里用到了一&#x4E2A;*\\*&#x5BB9;器，然后每个单独的滑块都分别使&#x7528;*\\*&#x6765;定义。也可以提供一些选项来定义滑块的行为；例如是否循环是否分页。（后续会有完整示例）

### 输入 Input

Ionic 2中使&#x7528;*\\*&#x6765;代&#x7801;*\\*。跟普通&#x7684;*\\*&#x4E00;样，可以根据你想要获得的信息来给他指定类型，使用Ionic版的输入框可以享受Ionic为移动做的自定义设计的好处。

```markup
<ion-list>

    <ion-item>
        <ion-label fixed>Username</ion-label>
        <ion-input type="text" value=""></ion-input>
    </ion-item>

    <ion-item>
        <ion-label fixed>Password</ion-label>
        <ion-input type="password"></ion-input>
    </ion-item>

</ion-list>
```

就跟定制&#x7684;*\\*&#x4E00;样，Ionic提供了其他输入自定义的输入组件，&#x5982;*\\*，*\\*，*\\*&#x4EE5;&#x53CA;*\\*。

### 格子 Grid

Grid组件非常强大，可以用来创建复杂的布局。如果你对CSS框架比较熟悉，例如Bootstrap，那么你应该很熟悉这个概念。当往你的模板中添加组件的时候，通常都是一个接一个地显示，但是有了Grid你可以实现任何你想要的布局。\
他的工作方式是将元素以行与列（放在行里面）的方式边靠边。例如：

```markup
<ion-row>
    <ion-col></ion-col>
    <ion-col></ion-col>
</ion-row>
<ion-row>
    <ion-col></ion-col>
    <ion-col></ion-col>
    <ion-col></ion-col>
</ion-row>
```

以上代码将创建一个两行的布局，上面的布局有两列，下面的布局有三列。默认所有元素均匀分布，你也可以指定列的宽度：

```markup
<ion-row>
    <ion-col width-10></ion-col>
    <ion-col width-20></ion-col>
    <ion-col width-25></ion-col>
    <ion-col width-25></ion-col>
    <ion-col width-20></ion-col>
</ion-row>
```

以上代码将创建单独的一行，里面有5个不同宽度的列（你可以将列宽设置为100！）。\
所有可用宽度请参考[文档](http://ionicframework.com/docs/v2/components/#grid)。

### 图标 Icons

现在的应用大量用到图标，他比文本的伟大之处在于他可以漂亮的表达事物的表达内容。大部分时候，他更易用比按钮加上一个‘添加条目’之类的标签更好看。\
Ionic提供超多的图标，例如：

```markup
<ion-icon name="heart"></ion-icon>
```

你只需要指出你需要使用的图标的名字即可。甚至他可以根据iOS和Android平台来切换不同的图标以更好的适配平台。所有可用图标可在[此处](http://ionicframework.com/docs/ionicons/)查看。\
Ionic还有很多其他的组件，即使这里已经讲过的组件，也有很多其他的细节需要你去了解，所以建议先阅读一下[文档](http://ionicframework.com/docs/components/#overview)熟悉一下。
