Ionic

呼延曜灿
2023-12-01

一、Ionic2提供了一个简单的启动模板来快速支撑一个app,我们的app叫做githubIonic。

在你的终端:

$ ionic start githubIonic tutorial --v2 --ts

上面的命令会创建一个ionic项目基于教程模板,然后下载必要的npm包,我们将会使用TypeScript,这就是为什么我们要使用--ts。

www/index.html一般是app的入口程序。


<!DOCTYPE html>
<html lang="en">
<head>
  <title>Ionic</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

  <link ios-href="build/css/app.ios.css" rel="stylesheet">
  <link md-href="build/css/app.md.css" rel="stylesheet">
  <link wp-href="build/css/app.wp.css" rel="stylesheet">  
</head>
<body>

  <ion-app></ion-app>

  <!-- cordova.js required for cordova apps -->
  <script src="cordova.js"></script>
  <!-- Polyfill needed for platforms without Promise and Collection support -->
  <script src="build/js/es6-shim.min.js"></script>
  <!-- Zone.js and Reflect-metadata  -->
  <script src="build/js/Reflect.js"></script>
  <script src="build/js/zone.js"></script>
  <!-- the bundle which is built from the app's source code -->
  <script src="build/js/app.bundle.js"></script>
</body>
</html>


我们一般不会碰这里面的文件,注意<ion-app></ion-app>:这是我们程序的入口,这叫做我们程序的根组件


我们将使用lonic CLI来重新加载。

我们的Ionic将有三个主要页面,一个对于github的用户,一个对于github组织,另一个用户github库,最后两页视图只是用来显示我们可以与侧边栏导航,他们讲没有任何内容,但是,github用户界面将使你可以查看用户的详细信息。


删除app/pages下所有文件夹,并且清空app/theme/app.core.scss文件,我们可以用以下命令快速创造三个页面。

$ ionic g page users
$ ionic g page repos
$ ionic g page organizations

这将会创造三个同名的文件夹,g是generate的别名,所以你也可以使用

ioinc generate pageName


把内容替换成如下内容:

user.html

<ion-header>
  <ion-navbar>
    <button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Users</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <h3>Users view page</h3>
</ion-content>


repos.html

<ion-header>
  <ion-navbar>
    <button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Users</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding >
  <h3>Repos view page</h3>
</ion-content>


organizations.html

<ion-header><pre name="code" class="html">import {Component, ViewChild} from '@angular/core';
import {ionicBootstrap, Platform, MenuController, Nav} from 'ionic-angular';
import {StatusBar} from 'ionic-native';

// Comment out impor of pages we have deleted from the pages folder
//import {HelloIonicPage} from './pages/hello-ionic/hello-ionic';
//import {ListPage} from './pages/list/list';

import {UsersPage} from './pages/users/users';
import {ReposPage} from './pages/repos/repos';
import {OrganizationsPage} from './pages/organizations/organizations'

@Component({
  templateUrl: 'build/app.html'
})
class MyApp {
// Commented out for brevity
}

<ion-navbar> <button menuToggle> <ion-icon name="menu"></ion-icon> </button> <ion-title>Organizations</ion-title> </ion-navbar></ion-header><ion-content padding> <h3>Organizations view page</h3></ion-content>
 Ionic2自带一些组件 

<ion-navbar>负责导航栏,即一个导航组件。

menuToggle是用来做一个切换菜单的指令。

<ion-icon>负责处理图标,我们简单的给他取个名字。

<ion-title>展示页面标题

<ion-content>负责处理页面的的内容,并且其中有一个padding来表明有一点padding

现在我们把这些文件添加到导航,并且来到app/app.ts,我们会做一点改变,其中有个属性叫做pages,这就是显示在app.htmlde的导航视图。

<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)">
        {{p.title}}
      </button>
    </ion-list>
  </ion-content>

</ion-menu>

<ion-nav id="nav" [root]="rootPage" #content swipe-back-enabled="false"></ion-nav>


我们不会动这个文件,并且这个按钮有一个*ngFor=“let p of pages”的指令,这就是Angular 2执行重复的模板。

We will not touch this file too, we will just use it as it was generated. The button has an *ngFor="let p of pages" directive, this is how Angular 2 performs repeating in templates. It simply means loop through the pages collection and generate a template for each item in the collection. So if we change the value of the pages property, we change the content of the side nav.

<ion-nav>是显示页面导航,root属性绑定了rootpage,

import {Component, ViewChild} from '@angular/core';
import {ionicBootstrap, Platform, MenuController, Nav} from 'ionic-angular';
import {StatusBar} from 'ionic-native';

// Comment out impor of pages we have deleted from the pages folder
//import {HelloIonicPage} from './pages/hello-ionic/hello-ionic';
//import {ListPage} from './pages/list/list';

import {UsersPage} from './pages/users/users';
import {ReposPage} from './pages/repos/repos';
import {OrganizationsPage} from './pages/organizations/organizations'

@Component({
  templateUrl: 'build/app.html'
})
class MyApp {
// Commented out for brevity
}


UsersPage、ReopsPage和OrganizationsPage都是组件类,代表页面被搭建当单独的页面产生时,你可以检查user.ts、repos.ts,organizatgions.ts。

接下来我们将编辑页面属性来匹配我们的新界面。


app.ts:

class MyApp {
@ViewChild(Nav) nav: Nav;

// make UsersPage the root (or first) page
// rootPage: any = UsersPage;
rootPage: any = UsersPage;
pages: Array<{title: string, component: any}>;
constructor(
    private platform: Platform,
    private menu: MenuController
  ) {
    this.initializeApp();

    // set our app's pages
    this.pages = [
      // Comment out pages we deleted
      //{ title: 'Hello Ionic', component: HelloIonicPage },
      //{ title: 'My First List', component: ListPage }
      { title: 'Users', component: UsersPage },
      { title: 'Repos', component: ReposPage },
      { title: 'Organizations', component: OrganizationsPage }
    ];
  }
  // code commented out for brevity
}

二、获取github

我们可以获取Github用户从https://api.github.com/users,这个页面列出了大概30个json格式的github用户。

首先,我们需要创建一个用户模型,这个类是有我们所需要的用户字段,在项目中创建一个model文件夹,在这里面放置了以后我们想要的模型,在里面添加一个app/user.ts。

export class User {
  login: string;
  id: number;
  avatar_url: string;
  gravatar_id: string;
  url: string;
  html_url: string;
  followers_url: string;
  following_url: string;
  gists_url: string;
  starred_url: string;
  subscriptions_url: string;
  repos_url: string;
  events_url: string;
  received_events_url: string;
  type: string;
  site_admin: boolean;
  name: string;
  company: string;
  blog: string;
  location: string;
  email: string;
  hireable: string;
  bio: string;
  public_repos: number;
  public_gists: number;
  followers: number;
  following: number;
  created_at: string;
  updated_at: string;
}

我们不会使用这个模型的所有属性,现在我们定义了我们的模型,我们可以创建一个github用户提供者让我们把用户从github上下载下来,通过以下命令来产生一个provider。

ionic g provider github-users

我们稍微修改一下其中的文件:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

/*
  Generated class for the GithubUsers provider.

  See https://angular.io/docs/ts/latest/guide/dependency-injection.html
  for more info on providers and Angular 2 DI.
*/

import {User} from '../../models/user'
@Injectable()
export class GithubUsers {
  githubUsers:any =null;

  constructor(private http: Http) {}

  load(){
  if(this.githubUsers){
  //已经加载user
  return Promise.resolve(this.githubUsers);
  }

  //还没有加载user
  return new Promise(resolver => {
  // 我们正在使用Angular Http Provider来请求users
  //响应后把json的数据映射到json对象
  //在这之后处理user及其数据

  this.http.get('https://api.github.com/users')
  .map(res => <Array<Users>>(res.json()))
  .subscribe(users => {
  this.githubUsers=users;
  resolver(this.githubUsers);
  });
  });
  }
}


@Injectable()用来声明这是Services和Providers。

我们做的第一件事情是导入用户模型,然后注意load()这个方法,它替你加载了你想要的所有数据,你需要做的是输入json的路径,在本例中是....,并在某处调用GithubUsers.load。

最后,我们想要结果转化成一个user数组,我们通过map(res => <Array<Users>(res.json())>)来处理。


三、显示github用户

现在我们有自己的用户,可以让其显示出来,在这之前,我们需要测试是否需要从provider获取数据。

打开app/page/users/user.ts文件

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

// Import GithubUsers provider
import {GithubUsers} from '../../providers/github-users/github-users';
/*
  Generated class for the UsersPage page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@Component({
  templateUrl: 'build/pages/users/users.html',

  // Add the GithubUsers provider as part of our page component
  providers: [GithubUsers]
})
export class UsersPage {
  // Inject the GithubUsers in the constructor of our page component
  constructor(public nav: NavController, githubUsers: GithubUsers) {
    // Test whether the github provider returns data
    githubUsers
      .load()
      .then(function (users) {
        // Log the returned github users
        console.log(users)
      });
  }
}

我们做了一些修改,首先在顶部导入GithubUsers,之后使用Angular 2的provider,我们需要把他传入组件装饰器中,在这种情况下是@component,所以你会发现

[GithubUsers]是其中一种属性。

并且在UserPage的构造方法中,我们添加了githubUsers: GithubUsers作为其中一个参数,这就是如何在Angular 2中注入依赖,然后我们在构造函数中调用Load方法并且使用console.log(user)记录结果。

为了显示users在我们的页面上,我们需要在UserPage中有个局部变量,也就是一个user的数组,并且用于更新UserPage。


app/pages/users/user.ts

// Imports commented out for brevity

// Import User model
import {User} from '../../models/user';

@Component({
  // Commented out for brevity
})
export class UsersPage {
  // Declare users as an array of User model
  users: User[];

  // Inject the GithubUsers in the constructor of our page component
  constructor(public nav: NavController, githubUsers: GithubUsers) {
    // Test whether the github provider returns data
    githubUsers
      .load()
      // User arrow function notation
      .then(users => this.users = users);
  }
}

首先,导入User模型。接下来,我们声明一个user数组的局部变量在定义类之后,即users: User[];,这是TypeScript的方式来定义一个用户类的属性,这意味着User属性是一个User数组。最后,我们通过GithubUser Provider更新结果,我们使用箭头功能then(users => this.users = users),这个结果分配给局部变量user。我们现在编辑html视图来展示github用户,我们将会使用ion-list来提供一个列表。


<ion-header>
  <ion-navbar>
    <button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Users</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>

  <ion-list>
    <button ion-item *ngFor="let user of users">
      <ion-avatar item-left>
        <img [src]="user.avatar_url">
      </ion-avatar>
      <h2>{{ user.login }}</h2>
      <ion-icon ios="ios-arrow-forward" md="md-arrow-forward" item-right></ion-icon>
    </button>
  </ion-list>
</ion-content>

ion-list组件的作用用于呈现列表,list中的项目有一个ion-item,我们将遍历Angular 2所建成的指令,我们将遍历所有的用户通过*ngFor="let user of users".。

接下来,user在ion-avatar里面绑定用户属性,就是给图像添加一个边界,因为属性中有一个avatar_url,因此user.avatar_url。接下来再添加user.login。而ion-icon是用来加载图片的,你可以简单的使用<ion-icon name="arrow -forward"></ion-icon>,但是我们使用ios="ios-arrow-forward" md="md-arrow-forward"来演示如何使用特定平台的图标,如android和ios。


四、显示用户详情

接下来,我们将创建一个展示用户详情的页面。

<ion-header>
  <ion-navbar>
    <button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>{{login}} Details</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding >
  <h3>User Details view page</h3>
</ion-content>

我们把{{login}}放在视图标题,因为我们打算把user传递到这个视图中。

// Imports commented out for brevity

// Import User's Details Page
import {UserDetailsPage} from '../user-details/user-details';

@Component({
  // Code commented out for brevity
})
export class UsersPage {
  // Code commented out for brevity

  constructor(public nav: NavController, githubUsers: GithubUsers) {
   // Implementation commented out for brevity
  }

  // Navigate to user details page with the login as a parameter  
  goToDetails(event, login) {
    this.nav.push(UserDetailsPage, {
      login: login
    });
  }
}


首先,我们导入UserDetailsPage。之后我们添加一个方法来处理跳转,即goToDetail()。他携带了两个参数,一个event,即我们引发导航所做的操作,还有login(username)。Ionic处理跳转就像堆一样,意味页面是添加在其他页面的上方,这就是为什么你看到了this.nav.push,并且把页面推进跳转栈,后进先出,第二个参数是我们想要传递到下一页的参数。


app/page/user/user.html

<!-- HTML commented out for brevity -->
<ion-content padding>

  <ion-list>
    <button ion-item *ngFor="let user of users" (click)="goToDetails($event, user.login)">
      <!-- HTML commented out for brevity -->
    </button>
  </ion-list>
</ion-content>

最后,需要获得传给详情页的参数

import { Component } from '@angular/core';

// Add NavParams to get the naviagtion parameters
import { NavController, NavParams } from 'ionic-angular';

/*
  Generated class for the UserDetailsPage page.

  See http://ionicframework.com/docs/v2/components/#navigation for more info on
  Ionic pages and navigation.
*/
@Component({
  templateUrl: 'build/pages/user-details/user-details.html',
})
export class UserDetailsPage {
  login: string;

  constructor(public nav: NavController, navParams: NavParams) {
    // Retrieve the login from the navigation parameters
    this.login = navParams.get('login');
  }
}

我们只是很简单的添加NavParmas到已经存在的import让我能够获得跳转的参数。

之后,声明String类型的type。

我们把NavParmas provider注入构造参数,这让我们获得上一页传进来的参数,通过this.login = navParams.get('login')。


五、得到更多的用户细节

现在我们已经有了用户详细信息,我们需要他的具体的细节,要做到这一点,我们必须编辑GithubUser provider来处理请求,请求应该改成https://api.github.com/users/{login},最后面的参数是我们要传递进去的username/login.。

app/providers/github-users/github-users.ts

// Imports commented out for brevity

@Injectable()
export class GithubUsers {
  githubUsers: any = null;

  constructor(public http: Http) {}

  load() {
  // Implementation commented out for brevity
  }

  // Get user details from the github api  
  loadDetails(login: string) {
    // get the data from the api and return it as a promise
    return new Promise<User>(resolve => {
      // Change the url to match https://api.github.com/users/{username}<pre name="code" class="html"><ion-content padding>
  <ion-searchbar></ion-searchbar>
  <ion-list>
    <!--HTML commented out for brevity-->
  </ion-list>
</ion-content>

this.http.get(`https://api.github.com/users/${login}`) .map(res => <User>(res.json())) .subscribe(user => { resolve(user); }); }); }}
 

我们添加了一个loadDetails()方法,他接收一个字符串作为参数,并且返回一个promise类型的用户,因此返回一个new Promise<User>


六、添加搜索栏

这是我们应用程序的最后一个功能,我们会添加一个搜索栏,Ionic提供了一个自定义seachbar组件供我们使用。


app/pages/users/users.html

<ion-content padding>
  <ion-searchbar></ion-searchbar>
  <ion-list>
    <!--HTML commented out for brevity-->
  </ion-list>
</ion-content>

搜索背后的逻辑很简单,在我们有了列表之后,我们根据结果来更新我们的列表。github api使你可以使用以下uri结构:

https://api.github.com/search/users?q={searchParam}。

首先,我们创建一个provider方法来搜索在GithubUser中。


// Imports commented out for brevity

@Injectable()
export class GithubUsers {
  // Code commented out for brevity

  load() {
   // Method implementation commented out for brevity
  }

  // Get user details from the github api  
  loadDetails(login: string) {
    // Method implementation commented out for brevity
  }

  // Search for github users  
  searchUsers(searchParam: string) {
    // get the data from the api and return it as a promise
    return new Promise<Array<User>>(resolve => {
      // Change the url to match https://api.github.com/search/users?q={searchParam}
      this.http.get(`https://api.github.com/search/users?q=${searchParam}`)
        // Cast the result into an array of users. 
        // The returned json result has an items
        // property which contains the users
        .map(res => <Array<User>>(res.json().items))
        .subscribe(users => {
          resolve(users);
        });
    });
  }
}

app/pages/users/user.ts

// Imports commented out for brevity
@Component({
  // Code commented out for brevity
})
export class UsersPage {
  // Code commented out for brevity

  // Inject the GithubUsers in the constructor of our page component
  constructor(public nav: NavController, githubUsers: GithubUsers) {
    // Code commented out for brevity

    // Test if our seach function works.
    githubUsers
      .searchUsers('ganga')
      .then(users => console.log(users));
  }

  // Code commented out for brevity
}


七、简单的查询

我们只有当超过三个字符时才开始查询。

让我们来获取用户输入searchbar的值。


app/pages/users/user.html

<ion-content padding >
  <ion-searchbar (input)="search($event)"></ion-searchbar>
  <ion-list>
    <!-- HTML commented out for brevity -->
  </ion-list>
</ion-content>

app/pages/users/users.ts

// Imports commented out for brevity

@Component({
  // Commented out for brevity
})
export class UsersPage {
  // Commented out for brevity

  // Inject the GithubUsers in the constructor of our page component
  constructor(public nav: NavController, private githubUsers: GithubUsers) {
    // Implementation commented out for brevity
  }

  // Search for user's from github  
  // Handle input event from search bar
  search(searchTerm) {
    let term = searchTerm.target.value;

    // We will only perform the search if we have 3 or more characters
    if (term.trim() == '' || term.trim().length < 3) {
      // Get github users and assign to local user's variable
      this.githubUsers
        .load()
        // Load original users in this case
        .then(users => this.users = users)
    } else {
      // Get the searched users from github
      this.githubUsers.searchUsers(term)
        .then(users => this.users = users)
    }
  }
}

这里有两个主要的变化,我们增加了一个private关键字给githubUsers,这使得在整个类中都可以使用这个参数,

 类似资料: