第一章 介绍
欢迎!
欢迎学习使用Ionic 2 制作移动应用!本书会教会你关于Ionic 2的一切知识,从基础入门到制作应用发布到App商店。
阅读本书的人们也许角度会有所不同,有些人已经熟悉Ionic 1,有些人已经在开始体验Ionic 2,有些人可能都不知道。
无论你在哪一个水准,可能都不重要。因为本书所有课程都解释得明白彻底,没有对Ionic的任何猜测。
同时本书不介绍HTML,CSS和JavaScript。在开始学习本书之前,你需要对这些知识有基础的了解。如果想要重新温习一下这些知识的话,建议你看看以下网站:
本书有很多不同的部分,但是有三个不同的区域。我们有基础知识入手,然后进入到应用制作,最后是打包和提交应用。
本书的所有应用范例都是完全独立的。虽然随着进度推进,每个应用的复杂度一点一点的在增加,我都是基于在你没有学习之前的范例的假设之上解释每个范例的,
所以每个范例中会有一些重复的信息存在。
注意:如果你购买本书的时候附送了视频教程,我建议你先看完视频教程再阅读本书。这不是强制要求,但是他只是一个基本介绍,而不是作为一个普通进度去学习。
更新与勘误
Ionic 2目前还在开发中,意思是他还在变。他目前是相对稳定的,所以阅读本书的大部分内容是不会变动的,但是照目前来看直到发布版放出之前会有变动的。
(译者已经运行了本书的代码,译者的Ionic 2版本是3.1.1,可用的源代码已经在本译文的github同repo下)
我会经常根据框架的变动来更新本书,这些更新都是免费的。我更新本书的时候你应该可以收到新的下载链接的邮件通知。
我会保持关注更新和保证事务正常,但是,这是个大工程,如果你找到任何错问,请给我发邮件,我会尽快更新。
本书使用的一些约定
本书使用的布局其实不要解释太多,尽管如此,你还是要看一下:
这样的区块
意思是你要去执行的行为。例如,这些区块文本会告诉你去创建一个文件或者做一些代码变更。这些区块在范例里面很常见。这个语法很有用,因为他帮我向你区别展示在应用中需要变动的代码。
注意:你会遇到这样的区块。他包含了一些你当前做的事情的相关信息。
重要:你也会遇到一些这样的东西。这些都是一些需要特别注意的“陷阱”。
好了,讲的太多!开始动手吧!祝你好运!
更新日志
Version 12(本版) - 更新RC.3
- 少许bug fix和优化
- Giflist视频播放bug问题修复
..
(都是本书内容更新日志,先放着)
新概念
Ionic 1是建立在Angular 1上的,Angular 1是用来制作复杂和伸展性的JavaScript应用的。
Ionic基于Angular做的事情是提供了一系列的功能来使制作移动应用更简单。
然后,随着新一代的Angular 2的到来,带来了一系列的改动和改进。
Ionic如果想要使用Angular 2的话,那么也需要有所改变,然后这就是Ionic 2了。
简单来讲,得益于新的web标准,使用Ionic 2 和 Angular 2我们可以让app在移动终端表现得更好,伸缩性,重用性,模组功能等等。
由于引入了Angular2,开发应用的方式来很大的改变。有大量的概念变更,以及有些东西的少量变更,例如模板语法。
在Ionic 2中,模板看起来是这样的:
<ion-menu [content]="content">
<ion-toolbar>
<ion-title>Pages</ion-title>
</ion-toolbar>
<ion-content>
<ion-list>
<button ion-item *ngFor="let p of pages" (click)="openPage(p)"></button>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav id="nav" [root]="rootPage" #content></
和Ionic 1差别很大,你的JavaScript应该是这样子的:
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { HomePage } from './pages/home/home';
@Component({
template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
rootPage: any = HomePage;
constructor(platform: Platform) {
platform.ready().then(() => {
});
}
}
跟Ionic 1比起来差别相当的大。但是如果你熟悉EXMAScript 6或者TypeScript的话,这些变动对你来说应该不是什么难事,
但是,如果这对你来说是全新的概念的话(大部分人都是这样)这个转变可能会有一丢丢难度。
为帮助你的思想负担转变减轻负担,Ionic 2 aplha版本刚出来的时候,ES6和TypeScript对我来说是全新的概念,
但是在短暂的一个时期之后,我就如鱼得水了。现在我对新的语法和结构的感觉比Ionic 1更舒服。
本课内我们将广泛的设计到Ionic 2和Angular 2的新概念和语法。目的是给你一个初步的认识,我们后续会详细介绍。
ECMAScript 6 (ES6)
在了解ECMAScript 6之前,我们需要了解一下ECMAScript是什么。追溯历史可能有点太复杂,但是核心是:ECMAScript是一个标准,
JavaScript实现了这个标准。ECMAScript定义标准,浏览器执行这个标准。同样的,HTML标准(最新的HTML5)也是这个组织定义的,然后由浏览器提供商实现。
不同浏览器以不同的方法去实现这些标准,不同的功能有大量的不同的支持,这就是为什么有些东西在不同的浏览器里面表现不同。
HTML5规格是一个游戏规则改变者,某种程度上ECMAScript 6也是。
他将会为你的JavaScript代码带来非常巨大的改变,总的来讲,他使JavaScript编程更成熟的一门编程语言,可以更简单的hold大型的复杂的应用(这是JavaScirpt之前想都不敢想的)。
此刻我们不会继续深入ES6,因为这不是本书的主旨,但是我会给你展示几个示例,以便你感受一下。ES6引入到JavaScript的新功能包括:
类 Class
class Shape {
constructor (id, x, y) {
this.id = id
this.move(x, y)
}
move (x, y) {
this.x = x
this.y = y
}
}
这是个非常大的变动,如果你有过传统编程语言例如Java,C#的使用经验的话你应该非常熟悉。长久以来,许多人利用JavaScirpt的function来实现仿class结构,从来没有一个办法在JavaScript中使用真正的类。现在,他来了。如果你不知道什么是类,不要紧,后面有一整节课来讲解。
模组/模块 Module
// lib/math.js
export function sum (x, y) { return x + y }
export var pi = 3.141593
// someApp.js
import * as math from "lib/math"
console.log("2PI = " + math.sum(math.pi, math.pi))
// otherApp.js
import { sum, pi } from "lib/math"
console.log("2PI = " + sum(pi, pi))
模块功能允许你将代码代码,然后在任何其他地导入使用,这个功能在Ionic中会大量用到。我们后续会继续深入,实际上我们在应用中创建任何组件我们都会导出然后在任何地方导入。
Promise
Promise是之前通过服务(serivce)实现过的东西,例如之前的ngCordova,但是他们现在是原生支持的,意思就是你可以这样去写:
doSomething().then((response) => {
console.log(response);
});
块语法
目前来讲,如果你JavaScript中定一个变量,他就在定义他的函数内随处可用。ES6新的块语法范围功能允许你通过let关键字来定义一些块内变量,如下:
for (let i = 0; i < a.length; i++) {
let x = a[i];
}
如果你想在循环体外访问x变量的话,那么你就会得到undefined。
大箭头函数
译注:=> 相对于 -> c++里用到的
我最喜欢的功能之一是大箭头函数,你可以这么去浪:
someFunction((response) => {
console.log(response);
});
而不是之前这样:
someFunction(function(response){
console.log(response);
});
初次看到,你可能会觉得不咋滴,但是他可以让你保持函数中父类的范围内。
上面的范例中,当我们访问this关键字的时候,你就会访问到本体,但是在下面的函数中,你想要访问到本体的话需要这么做:
var me = this;
someFunction(function(response){
console.log(me.someVariable);
});
得益于新语法,我们就不需要创建一个this的静态引用了,我们可以直接使用this。
想要了解ES6的新功能,请查看这里:http://es6-features.org/
TypeScript
另一个需要浏览一下的改变是TypeScript,我们在Ionic 2中需要用到。需要重点指出的是尽管Ionic 2用来TypeScript,你不一定需要用他来制作Ionic 2应用,你可以可以用纯ES6。话虽如此,TypeScript提供了额外的功能(特别是依赖注入)使事情简单化,很快他将会成为Ionic 2的标配,所以说不用他说没有道理的。
本书将使用TypeScript,所以我们深入了解一下他是什么以及他和纯ES6的区别是什么。TypeScript自己的网站上是这么定义他自己的:
“一个有类型的JavaScript的子集,编译成纯JavaScript”
可能你看了这段描述之后还是摸不着头脑TypeScript到底是啥(虽然相对于it世界的茫茫宇宙,这段描述看起来相当简单)。实际上,在StackOverFlow上有一个帖子更详细的解释了TypeScript是什么—基本上,TypeScript为javascript增加了类型,类和接口。
通过TypeScript,你可以更严谨的去编程,就跟其他面向对象的语言(如Java,C#)一样。JavaScript原本就不是设计用来做复杂应用的。虽然我们之前了解过JavaScript可以通过函数来实现仿类的行为,但是还是不够简洁。
但是,我之前说过ES6已经可以创建类了,为什么我们还是要用TypeScript?我看到一个Redditor说的很简单:
“他叫做TypeScript,不叫ClassScript”
TypeScript始终提供了JavaScript的静态类型(意思是在编译时评估,与动态类型不同,是在运行时评估)。在TypeScript中使用类型是这样的:
function add(x: number, y :number):number {
return x + y;
}
add('a', 'b'); // compiler error
以上代码陈述了x必须是number类型(x : number),y必须是number类型(y : number),add函数需要返回一个number类型的值add():number。因此,在这个例子中,我们将会收到报错,因为我们向一个只接受number类型的函数传入字符类型。这种制作大型应用的时候非常有用,添加了一层检查来预防bug。
如果你之前的Ionic 2代码的话:
export class MyApp {
rootPage: any = HomePage;
constructor(platform: Platform) {
platform.ready().then(() => {
});
}
}
你可以发现一些TypeScript特性在发挥作用。以上代码告诉你rootPage可以是any类型,any是一个特殊类型,意思是可以是任何类型,platform是一个Platform类型。稍后,你将看到,对于依赖注入来讲,给事物进行类型限定是非常方便。
由于TypeScript是Ionic 2默认使用的,也许大多数人在使用的,所以本书专注于使用TypeScript。绝大部分ES6和TypeScript项目看起来非常像,在两者之间转换是非常简单的。
转译
转译的意思是将一种语言转换成另一种语言。为什么这个对我们来说很重要?基本上,EXMAScript 6提供给我们很多新鲜玩意,但是ES6只是个标准,还没有浏览器完全支持。我们得使用转译器将ES6转换成ES5(你现在在用的JavaScript)代码以协调浏览器。
在Ionic应用中,通过以下几个步骤来实现:
- 使用ionic serve运行应用
- app文件夹内的所有代码都转译到有效的ES5代码
- 将会创建一个打包好的JavaScript代码包并运行之
你不用去关心这个流程,因为Ionic自动帮你完成他。
网络组件
网络组件是Angular 2里面的大玩意,在Angualar 1中不是很好用。网络组件也不是Angular独有的,他们已经逐步成为了网络上的标准,用来创建模块,自包含,作为一小段代码很容易插入到页面中(跟WordPress中的Widget有点类似)。
“In a nutshell, they allow us to bundle markup and styles into custom HTML elements.” - Rob Dodson
Rob Dodson写的这篇关于网络组件的文章,解释了他们是怎么工作的,以及他们背后的理念是什么。同时,他提供一个很好的例子,我觉得一步到位的解释了为何网络组件非常有用。
一般来讲,如果你要添加一个图片滑动作为网络组件,HTML应该是这样的:
<img-slider>
<img src="images/sunset.jpg" alt="a dramatic sunset">
<img src="images/arch.jpg" alt="a rock arch">
<img src="images/grooves.jpg" alt="some neat grooves">
<img src="images/rock.jpg" alt="an interesting rock">
</img-slider>
而不是这样的(没用到网络组件):
<div id="slider">
<input checked="" type="radio" name="slider" id="slide1" selected="false">
<input type="radio" name="slider" id="slide2" selected="false">
<input type="radio" name="slider" id="slide3" selected="false">
<input type="radio" name="slider" id="slide4" selected="false">
<div id="slides">
<div id="overflow">
<div class="inner">
<img src="images//rock.jpg">
<img src="images/grooves.jpg">
<img src="images/arch.jpg">
<img src="images/sunset.jpg">
</div>
</div>
</div>
<label for="slide1"></label>
<label for="slide2"></label>
<label for="slide3"></label>
<label for="slide4"></label>
</div>
在不远的将来,你不需要去下载jQuery插件,然后复制粘贴一堆的HTML到你的文档中,你只需要导入这个网络组件,然后像上面那样子添加一个简单的图片滑动代码,就可以用来。
网络组件非常有趣,如果想要知道他们是怎么工作的(例如Shadow Dom和Shadow Boundaries),那么,我强烈推荐你读一遍:
Rob Dodson关于网络组件这个帖子。