【前端】Angular2 Ionic2 学习记录
转载请注明出处:http://www.cnblogs.com/shamoyuu/p/angular2_ionic2.html
一、建立项目
ionic start ProductName super
super是ionic提供的一个拥有完整功能的小项目,可以参考学习,如果想创建空项目就用
ionic start ProductName blank
当然参数还有很多,比如--no-git等等,可以通过下面的指令查看
ionic start --help
二、添加i18n国际化
首先安装需要的依赖,这个版本号是基于@angular/core@4.1.3的,如果@angular/core升级了,这里也应该对应去升级,在添加依赖的时候会提示它需要支持的版本号
cnpm install --save @ngx-translate/core@6.0.1
cnpm install --save @ngx-translate/http-loader@0.0.3"
然后新建 src/assets/i18n/zh.json 文件
然后在app.module.ts文件中引入
import {HttpModule, Http} from '@angular/http';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
在最上面添加下面的方法
//translate加载器需要知道从ionic的哪个静态管道加载i18文件
export function HttpLoaderFactory(http: Http) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
修改imports
imports: [
BrowserModule,
HttpModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [Http]
}
}),
IonicModule.forRoot(MyApp)
],
到此就引入完成,然后就可以用了TranslateService
打开app.component.ts文件,引入TranslateService,然后把它添加到构造器的引用里面private translateService: TranslateService
import {TranslateService} from '@ngx-translate/core';
添加一个方法
initTranslate(){
this.translateService.setDefaultLang('zh'); if (this.translateService.getBrowserLang() !== undefined) {
this.translateService.use(this.translateService.getBrowserLang());
} else {
this.translateService.use('zh');
}
}
然后在constructor里调用这个方法
this.initTranslate();
就可以用了
this.translateService.get(['tabs.tab1', 'tabs.tab2', 'tabs.tab3', 'tabs.tab4']).subscribe(values => {
this.tab1Title = values['tabs.tab1'];
this.tab2Title = values['tabs.tab2'];
this.tab3Title = values['tabs.tab3'];
this.tab4Title = values['tabs.tab4'];
});
三、统一的API数据及错误处理
如果我们不进行处理,那么每一个请求的subscribe方法我们都要自己写error方法来提示用户网络错误,后台错误,用户未登录等等等等其他各种各样的错误。很显然我们需要一个统一的方法
首先我们在api.ts最下面添加两个接口(当然你也可以每个做一个单独的文件)来约定我们的后台应该返回什么样格式的数据,还有我们的错误信息应该有哪些数据。习惯了js开发的同学可能会有点陌生,可以把这两个接口理解成两个对象。
/**
* 统一的后台返回的数据
*/
export interface ApiData {
stateCode: number; //状态码,0表示成功,大于0则表示各种失败的原因(例如1是未登录,2是后台报错等等)
message?: string; //错误信息,只有在stateCode不为0时才有值
data?: any; //需要的数据,stateCode为0时才有值
} /**
* 错误信息
*/
export interface ErrorData {
errorObservable: Observable<any>; //数据由此而来
toastController: ToastController; //因为showError是个方法,不方便注入,所以从父级传入。如果想手动注入可以参考ReflectiveInjector.resolveAndCreate方法
}
然后我们新建一个文件errorInfo.ts文件,这个类用来获取错误信息,返回一个Observable<any>,这个类是全局单例,需要自动注入,所以别忘了加到AppModule里面
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {TranslateService} from '@ngx-translate/core';
import {ApiData} from './api'; /**
* 根据所有数据获取错误信息
*/
@Injectable()
export class ErrorInfo {
// 处理请求被放弃
private cancel(status, headers, data): Observable<any> {
return Observable.create(function (observer) {
observer.next("");
});
} // 处理网络异常
private network(status, headers, data): Observable<any> {
return this.translateService.get('stateTexts.networkAnomaly')
} // 请求超时
private timeout(status, headers, data): Observable<any> {
return this.translateService.get('stateTexts.timeoutException')
} // 处理 HTTP 异常
private http(dstatus, headers, data): Observable<any> {
return this.translateService.get('stateTexts.serviceException')
} // 处理用户未登陆异常
private notLogin(status, headers, data): Observable<any> {
//TODO 登录
return Observable.create(function (observer) {
observer.next(data.message);
});
} // 处理其它异常操作
private other(status, headers, data): Observable<any> {
return Observable.create(function (observer) {
observer.next(data.message);
});
} constructor(private translateService: TranslateService) {
} public getErrorInfo(status: number, headers: any, data?: ApiData): Observable<any> {
if (status < 200 || status >= 300) {
return this.http(status, headers, data);
}
// 业务异常
else if (data && data.stateCode) {
// 用户未登录
if (data.stateCode == 1) {
return this.notLogin(status, headers, data);
}
// 其它异常
else {
return this.other(status, headers, data);
}
}
else if (data && data.message) {
// 其它异常
return this.other(status, headers, data);
}
else {
//数据格式错误
return this.http(status, headers, data);
}
}
}
然后需要在语言文件zh.json文件里添加下面的数据
"stateTexts": {
"unknownException": "未知异常,请刷新重试。",
"notLogin": "用户未登录",
"networkAnomaly": "网络异常",
"timeoutException": "请求超时",
"serviceException": "服务器繁忙,请您稍后再试。"
}
然后新建一个showError.ts文件,它只用来export一个function,这玩意就是用来统一处理错误的(虽然它只是创建了一个toast然后展示了一下错误信息)
import {ToastController} from 'ionic-angular'; /*
* 统一的Api错误展示
*/
export function showError(errorData: any) {
errorData.errorObservable.subscribe(msg => {
let toast = errorData.toastController.create({
message: msg,
duration: 3000,
showCloseButton: true,
closeButtonText: '×'
});
toast.present();
});
}
toast具体的api可以看官方的文档 http://ionicframework.com/docs/api/components/toast/ToastController/
然后我们来处理api里的get方法,其他方法也是一样的,我就不贴了
首先需要在constructor里注入我们需要的errorInfo和toastController,然后改写get方法如下
public get(endpoint: string, params?: any, options?: RequestOptions) {
if (!options) {
options = new RequestOptions();
} if (params) {
let par = new URLSearchParams();
for (let key in params) {
par.set(key, params[key]);
} options.search = !options.search && par || options.search;
} let observable = this.http.get(this.url + "/" + endpoint, options); //这里必须先捕获catch的错误,否则后面throw的错会在这里捕获
//map是直接返回value,mergeMap是返回Observable.of(value),所以这里要用mergeMap
return observable.catch((erro: Response) => {
let errorData: ErrorData = Object.create(null);
errorData.errorObservable = this.errorInfo.getErrorInfo(erro.status, erro.headers);
errorData.toastController = this.toastController;
return Observable.throw(errorData);
}).mergeMap(res => {
let data = res.json();if(data.stateCode != 0){
let errorData: ErrorData = Object.create(null);
errorData.errorObservable = this.errorInfo.getErrorInfo(res.status, res.headers, data);
errorData.toastController = this.toastController;
return Observable.throw(errorData);
} else {
return Observable.create(function (observer) {
observer.next(data.data);
observer.complete();
});
}
});
}
Observable.throw会触发subscribe里的error方法,参数也会传过去,我们这里传入了一个ErrorData
在下面的Observable.create是在网络和数据都没有错误的时候触发
Observable其他的方法可以参考官方api http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html
至此,我们所有的准备工作都做完了,使用的时候,只需要引入showError,然后在subscribe的第二个参数里填入它就好了
this.userService.getList().subscribe(
values => {
this.users = values.list;
},
showError,
() => console.info("请求已完成"))
我们后台返回的数据是这样的,但是前端不需要去考虑stateCode、data和message,只需要考虑data里的数据就好
{
"stateCode": 0,
"data": {
"list": [
{
"id": 1,
"username": "静茹♂ 鱼"
},
{
"id": 2,
"username": "一花一世界,一叶一追寻"
}
]
}
}
如果我们请求的地址404的话,就会自动弹出toast了
四、组件间通讯的MessageCenter
import {Injectable, EventEmitter} from '@angular/core'; /**
* 消息中心,提供一个全消息注册及广播服务,作为各模块之间通信使用
*
* this.messageCenter.subonce("msg", data => console.info("第一次订阅", data));
* this.messageCenter.subonce("msg", data => console.info("第二次订阅", data));
* this.messageCenter.pubonce("msg", {x: 1, y: 2});
* 带有once的方法是只能订阅一次,后面订阅的会覆盖前面的,会打印【第二次订阅 {x: 1, y: 2}】
*
* this.messageCenter.subscribe("msg", data => console.info("第一次订阅", data));
* this.messageCenter.subscribe("msg", data => console.info("第二次订阅", data));
* this.messageCenter.publish("msg", {x: 1, y: 2});
* 不带once的方法可以多次订阅,所有订阅的方法都会按顺序执行,会答应【第一次订阅 {x: 1, y: 2}】和【第二次订阅 {x: 1, y: 2}】
*
* 当然,他们是成套使用的
*/
@Injectable()
export class MessageCenter {
//用来存储可以重复订阅的事件
private eventList: any = {};
//用来存储只能订阅一次的事件,后面相同的订阅会覆盖前面的
private onceEventList: any = {}; constructor(){} /**
* 发送消息
* @param messageNames 消息名称
* @param callback 回调函数
*/
public subscribe(messageName, callback){
if(!this.eventList[messageName]){
this.eventList[messageName] = new EventEmitter();
}
this.eventList[messageName].subscribe(callback);
} /**
* 发送消息
* @param messageNames 消息名称,也可以是数组
* @param data 需要发送的数据
*/
public publish(messageNames, data){
if(typeof messageNames === "string"){
messageNames = [messageNames];
}
for(let i = 0; i < messageNames.length; i++){
this.eventList[messageNames[i]] && this.eventList[messageNames[i]].emit(data);
}
} /**
* 用来订阅一次的消息
* @param messageName 消息名称
* @param callback 回调函数
*/
public subonce(messageName, callback){
this.onceEventList[messageName] = callback;
} /**
* 用来发送订阅一次的消息
* @param messageNames 消息名称,也可以是数组
* @param data 需要发送的数据
*/
public pubonce(messageNames, data){
if(typeof messageNames === "string"){
messageNames = [messageNames];
}
for(let i = 0; i < messageNames.length; i++){
this.onceEventList[messageNames[i]] && this.onceEventList[messageNames[i]](data);
}
}
}
然后就可以随意使用了,特别方便
【前端】Angular2 Ionic2 学习记录的更多相关文章
- 网页前端之JavaScript学习记录总结篇
咔咔咔咔咔咔扩扩扩扩扩扩扩扩扩扩
- 网页前端之CSS学习记录总结篇
标签: 块级标签block:div, p, h1-h6, ul, ol,li, dl, dt, dd,table,tr等,独占一行,可以设置宽高,默认是父标签的100%:行内标签inline:a,sp ...
- 前端学习记录之Javascript-DOM
简介 为了快捷方便,在工作和项目中,一直都是使用的框架,比如jqeruy,vuejs,react等.然后在长时间使用框架后,往往有一个后遗症,就是对于原生的Javascript基本上已经不知道怎么写了 ...
- 前端学习记录 week 1
前端学习记录 week 1 基础知识 CSS盒模型 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用.CSS盒模型本质上是一个盒子,封 ...
- 4.VUE前端框架学习记录四:Vue组件化编码2
VUE前端框架学习记录四:Vue组件化编码2文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...
- 3.VUE前端框架学习记录三:Vue组件化编码1
VUE前端框架学习记录三:Vue组件化编码1文字信息没办法描述清楚,主要看编码Demo里面,有附带完整的代码下载地址,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/ ...
- 2.VUE前端框架学习记录二
VUE前端框架学习记录二:Vue核心基础2(完结)文字信息没办法描述清楚,主要看编码实战里面,有附带有一个完整可用的Html页面,有需要的同学到脑图里面自取.脑图地址http://naotu.baid ...
- 1.VUE前端框架学习记录一
VUE前端框架学习记录一文字信息没办法描述清楚,主要看编码实战里面,有附带有一个完整可用的Html页面,有需要的同学到脑图里面自取.脑图地址http://naotu.baidu.com/file/f0 ...
- [前端学习]vue的指令学习记录 vu-if | text | for | on | model | bind | pre
vue的指令学习记录 vue-if | text | for | on | model - 目录 vue的指令学习记录 vue-if | text | for | on | model ... 预备 ...
随机推荐
- 小白的Python之路 day5 re正则模块
re正则模块 一.概述 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,要讲他的具体用法要讲一本书!它内嵌在Python中,并通过 re 模块实现.你可以为想要匹配的相应字符串 ...
- all,any函数
all函数:当矩阵全为非零元素时返回1,否则(存在零元素),返回0: any函数:当矩阵中存在非零 1 1 1 1 1 1 1 1 ...
- cobbler自动化安装系统
笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 在很久很久以前,使用kickstart实现自动化安装的时候,我一直认为装系统是多么高大上的活,直到cobbler的 ...
- office2013使用空格符
空格符:所有的空格都以点表示出来. 作用:挑出空格符后,可以很方便的看到所有的空格,分页符等,使页面更容易调整的工整(在写正规的word文档时,需要这样做). 用法:很简单,根据图片上操作的顺序即可调 ...
- 以Apache模块的方式编译安装php-5.4.27
为什么要安装低版本的php? 由于apc,xcache的更新版本跟不上php版本的速度,所以,我们需要安装比较稳定的php低版本程序,再安装其它与之相匹配的扩展. 开工: 新建用户及用户组 group ...
- 根据 inotify 自己开发软件监控文件系统活动
了解 inotify Inotify 是一个 Linux 内核特性,它监控文件系统,并且及时向专门的应用程序发出相关的事件警告,比如删除.读.写和卸载操作等.您还可以跟踪活动的源头和目标等细节. 使用 ...
- 使用.bat来执行Java程序基础
将java程序做成可运行的jar后,又希望使用.bat文件来调用jar时,有几点需要注意的. 1.设置path和classpath .bat文件中扥的内容如下: @echo off set MY_HO ...
- MOBA服务器开发第一阶段完成总结
开发历程 项目是从8月20日左右开始开发的,到今天一个月不到吧. 除了底层库和服务器架构外我们大致开发了5个服务器为: 一 ) . 战斗服务器 二 ) . 匹配服务器 三 ) . 验证服务器 四 ) ...
- Linux C 一个简单的线程池程序设计
最近在学习linux下的编程,刚开始接触感觉有点复杂,今天把线程里比较重要的线程池程序重新理解梳理一下. 实现功能:创建一个线程池,该线程池包含若干个线程,以及一个任务队列,当有新的任务出现时,如果任 ...
- java设计模式在公众号的应用——我是一个快乐的单例
终于可以休息了,寻一把躺椅,安置于庭院,携一壶好茶,品一番风轻云淡... 自由自在的呼吸,伸手即可触摸阳光的温度,此时此刻,我就是我,像一个单例. 想起『设计模式』,就像想起了很久很久以前的故事,今日 ...