Angular7入門總結篇

Angular7入門總結篇

6<time datetime="2019-01-08T11:34:05.000Z" style="box-sizing: border-box; margin-right: 8px;">2019.01.08 19:34:05</time>字數(shù) 4854閱讀 46093

<article class="_2rhmJa" style="box-sizing: border-box; display: block; font-weight: 400; line-height: 1.8; margin-bottom: 20px; color: rgb(64, 64, 64); font-family: -apple-system, BlinkMacSystemFont, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">

發(fā)表于 http://blog.poetries.top/2019/01/09/angular7-intro-summary

最近在學Ionic4外盯,不得不學習angular宋彼、Typescript基礎知識誊涯,這里簡單總結記錄一下放坏。

一蚤认、Angular 介紹

Angualr 是一款來自谷歌的開源的 web 前端框架辛萍,誕生于 2009 年儒搭,由 Misko Hevery 等 人創(chuàng)建悲柱,后為 Google 所收購捧请。是一款優(yōu)秀的前端 JS 框架凡涩,已經(jīng)被用于 Google 的多款產(chǎn)品當中。

  • 根據(jù)項目數(shù)統(tǒng)計 angular(1.x 疹蛉、2.x 活箕、4.x、5.x可款、6.x育韩、7.x)是現(xiàn)在網(wǎng)上使用量最大的框架
  • Angualr 基于 TypeScriptreactvue 相比, Angular 更適合中大型企業(yè)級項目闺鲸。

目前 2018 年 11 月 25 日 angular 最新版本 angular7.x筋讨。根據(jù)官方介紹,Angular 每過幾個月 就會更新一個版本摸恍。此教程同樣適用于后期更新的 Angular8.x悉罕、Angular9.x

image

學習 Angular 必備基礎

必備基礎:htmlcss 立镶、js壁袄、es6Typescript

二媚媒、Angular 環(huán)境搭建及創(chuàng)建項目

2.1 環(huán)境搭建

1. 安裝 nodejs

安裝 angular 的計算機上面必須安裝最新的 nodejs--注意安裝 nodejs 穩(wěn)定版本

2. 安裝 cnpm

npm 可能安裝失敗建議先用 npm 安裝一下 cnpm 用淘寶鏡像安裝https://npm.taobao.org

npm install -g cnpm --registry=https://registry.npm.taobao.org

3. 使用 npm/cnpm 命令安裝 angular/cli

npm install -g @angular/cli 

# 或者 
cnpm install -g @angular/cli

ng v 查看版本信息

image

4. 安裝插件

image

5. 安裝chrome擴展

</article>

augury查看component結構嗜逻,更方便調試

image

2.2 創(chuàng)建項目

# 創(chuàng)建項目
ng new my-app

cd my-app

# 運行項目
ng serve --open

2.3 目錄結構分析

image

詳情參考 https://www.angular.cn/guide/file-structure

app目錄(重點)

app目錄是我們要編寫的代碼目錄。我們寫的代碼都是放在這個目錄缭召。
一個Angular程序至少需要一個模塊和一個組件栈顷。在我們新建項目的時候命令行已經(jīng)默認生成出來了

image
  • app.component.ts:這個文件表示組件,
  • 組件是Angular應用的基本構建模塊嵌巷,可以理解為一段帶有業(yè)務邏輯和數(shù)據(jù)的Html
    我們來看看app.component.ts中的代碼萄凤,并解釋下代碼的意義
image
/*這里是從Angular核心模塊里面引入了component裝飾器*/
import {Component} from '@angular/core';

/*用裝飾器定義了一個組件以及組件的元數(shù)據(jù)  所有的組件都必須使用這個裝飾器來注解*/
@Component({
  /*組件元數(shù)據(jù)  Angular會通過這里面的屬性來渲染組件并執(zhí)行邏輯
  * selector就是css選擇器,表示這個組件可以通過app-root來調用晴竞,index.html中有個<app-root>Loading...</app-root>標簽蛙卤,這個標簽用來展示該組件的內容
  *templateUrl  組件的模板,定義了組件的布局和內容
  *styleUrls   該模板引用那個css樣式
  * */
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
/*AppComponent本來就是一個普通的typescript類,但是上面的組件元數(shù)據(jù)裝飾器告訴Angular颤难,AppComponent是一個組件神年,需要把一些元數(shù)據(jù)附加到這個類上,Angular就會把AppComponent當組件來處理*/
export class AppComponent {
  /*這個類實際上就是該組件的控制器行嗤,我們的業(yè)務邏輯就是在這個類中編寫*/
  title = '學習Angular';
}

組件相關的概念

  1. 組件元數(shù)據(jù)裝飾器(@Component
    簡稱組件裝飾器已日,用來告知Angular框架如何處理一個TypeScript類.
    Component裝飾器包含多個屬性,這些屬性的值叫做元數(shù)據(jù)栅屏,Angular會根據(jù)這些元數(shù)據(jù)的值來渲染組件并執(zhí)行組件的邏輯
  2. 模板(Template
    我們可以通過組件自帶的模板來定義組件的外觀飘千,模板以html的形式存在,告訴Angular如何來渲染組件栈雳,一般來說护奈,模板看起來很像html,但是我們可以在模板中使用Angular的數(shù)據(jù)綁定語法哥纫,來呈現(xiàn)控制器中的數(shù)據(jù)霉旗。
  3. 控制器(controller
    控制器就是一個普通的typescript類,他會被@Component來裝飾蛀骇,控制器會包含組件所有的屬性和方法厌秒,絕大多數(shù)的業(yè)務邏輯都是寫在控制器里的秃嗜×《校控制器通過數(shù)據(jù)綁定與模板來通訊,模板展現(xiàn)控制器的數(shù)據(jù)概疆,控制器處理模板上發(fā)生的事件暑诸。

裝飾器蚌讼,模板和控制器是組件的必備要素。還有一些可選的元素屠列,比如:

  • 輸入屬性(@inputs):是用來接收外部傳入的數(shù)據(jù)的,Angular的程序結構就是一個組件樹啦逆,輸入屬性允許在組件樹種傳遞數(shù)據(jù)
    提供器(providers):這個是用來做依賴注入的
  • 生命周期鉤子(LifeCycle Hooks):一個組件從創(chuàng)建到銷毀的過程中會有多個鉤子會被觸發(fā)伞矩,類似于Android中的Activity的生命周期
  • 樣式表:組件可以關聯(lián)一些樣式表
  • 動畫(Animations): Angular提供了一個動畫包來幫助我們方便的創(chuàng)建一些跟組件相關的動畫效果笛洛,比如淡入淡出等
  • 輸出屬性(@Outputs):用來定義一些其他組件可能需要的事件或者用來在組件之間共享數(shù)據(jù)

組件的中關系就如下圖所示

image

下面我們來看看模塊文件

  • app.module.ts:這個文件表示模塊
  • AppComponent類似,模塊也需要裝飾器來裝飾
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HeroesComponent } from './heroes/heroes.component';

@NgModule({
  declarations: [
   // 聲明模塊里有什么東西 只能聲明:組件/指令/管道
    AppComponent,
    HeroesComponent
  ],
  // 聲明該模塊所依賴的模塊
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  // 默認情況下是空的
  providers: [],
  // 聲明模塊的主組件是什么
  bootstrap: [AppComponent]
})
export class AppModule { }

2.4 Angular cli

https://cli.angular.io

通過ng g列出當前命令

image

1. 創(chuàng)建新組件 ng generate component component-name

ng g component components/header 指定生成到哪個目錄

該命令會把生成的組件乃坤,添加到 src/app/app.module.ts 文件中 @NgModuledeclarations 列表中聲明

image

2. 使用 Angular CLI 創(chuàng)建一個名叫 hero 的服務

ng generate service hero

該命令會在 src/app/hero.service.ts 中生成 HeroService 類的骨架苛让。 HeroService 類的代碼如下:

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

@Injectable({
  providedIn: 'root',
})
export class HeroService {

  constructor() { }

}

3. 添加 AppRoutingModule

ng generate module app-routing --flat --module=app

  • --flat 把這個文件放進了 src/app 中,而不是單獨的目錄中湿诊。
  • --module=app 告訴 CLI 把它注冊到 AppModuleimports 數(shù)組中狱杰。

生成的文件是這樣的:

src/app/app-routing.module.ts (generated)
content_copy
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
  imports: [
    CommonModule
  ],
  declarations: []
})
export class AppRoutingModule { }

修改后

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

三、angular組件及組件里的模板

3.1 創(chuàng)建angualr組件

1. 創(chuàng)建組件

ng g component components/header

2. 使用組件

<app-header></app-header>

3.2 Angular 綁定數(shù)據(jù)

1. 數(shù)據(jù)文本綁定

定義數(shù)據(jù)幾種方式

image
<h1>{{title}}</h1>

2. 綁定HTML

 this.h="<h2>這是一個 h2 用[innerHTML]來解析</h2>"

 <div [innerHTML]="h"></div>

3.3 聲明屬性的幾種方式

  • public 共有(默認) 可以在類里外使用
  • protected 保護類型 只能在當前類和子類中使用
  • private 私有類型 只能在當期類使用

3.4 綁定屬性

[]包裹

 <div [id]="id" [title]="msg">調試工具看看我的屬性</div>

image

3.5 數(shù)據(jù)循環(huán) *ngFor

*1. ngFor 普通循環(huán)

export class HomeComponent implements OnInit {

  arr = [{ name: 'poetries', age: 22 }, { name: 'jing' , age: 31}];
  constructor() { }

  ngOnInit() {
  }

}

<ul *ngIf="arr.length>0">
      <li *ngFor="let item of arr">{{item.name}}- {{item.age}}</li>
</ul>

2. 循環(huán)的時候設置 key

<ul>
<li *ngFor="let item of list;let i = index;"> <!-- 把索引index賦給i -->
     {{item}} --{{i}}
</li> </ul>

3. template 循環(huán)數(shù)據(jù)

<ul>
  <li template="ngFor let item of list">
{{item}}
</li> </ul>

3.6 條件判斷 *ngIf

<p *ngIf="list.length > 3">這是 ngIF 判斷是否顯示</p>

<p template="ngIf list.length > 3">這是 ngIF 判斷是否顯示</p>

3.7 *ngSwitch

<ul [ngSwitch]="score">
<li *ngSwitchCase="1">已支付</li>
<li *ngSwitchCase="2">訂單已經(jīng)確認</li> <li *ngSwitchCase="3">已發(fā)貨</li>
<li *ngSwitchDefault>無效</li>
</ul>

3.8 執(zhí)行事件 (click)=”getData()”

<button class="button" (click)="getData()"> 點擊按鈕觸發(fā)事件
</button>
<button class="button" (click)="setData()"> 點擊按鈕設置數(shù)據(jù)
</button>

getData(){ /*自定義方法獲取數(shù)據(jù)*/ //獲取
  alert(this.msg);
} 
setData(){
    //設置值
    this.msg='這是設置的值';
}

3.9 表單事件

<input
type="text"
(keyup)="keyUpFn($event)"/>

<input type="text" (keyup)="keyUpFn($event)"/>

keyUpFn(e){
    console.log(e)
}

3.10 雙向數(shù)據(jù)綁定

<input [(ngModel)]="inputVal">

注意引入:FormsModule

import {FormsModule} from '@angular/forms'

NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    FooterComponent,
    NewsComponent
  ], 
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

<!--使用-->
<input type="text" [(ngModel)]="inputValue"/> {{inputValue}}

3. 11 [ngClass]厅须、[ngStyle]

1. [ngClass]:

<div [ngClass]="{'red': true, 'blue': false}"> 
    這是一個 div
</div>

public flag=false;

<div [ngClass]="{'red': flag, 'blue': !flag}">
這是一個 div </div>

public arr = [1, 3, 4, 5, 6];

<ul>
<li *ngFor="let item of arr, let i = index"> <span [ngClass]="{'red': i==0}">{{item}}</span>
</li> </ul>

2. [ngStyle]:

<div [ngStyle]="{'background-color':'green'}">你好 ngStyle</div>

public attr='red';

<div [ngStyle]="{'background-color':attr}">你好 ngStyle</div>

3.12 管道

 public today=new Date();

 <p>{{today | date:'yyyy-MM-dd HH:mm:ss' }}</p>

其他管道

angular中的管道(pipe)是用來對輸入的數(shù)據(jù)進行處理仿畸,如大小寫轉換、數(shù)值和日期格式化等

angular中的管道(pipe) 以及自定義管道適用于angular4 angualr5 angualr6 angular7

常用的管道(pipe)有

1. 大小寫轉換

<!--轉換成大寫-->
<p>{{str | uppercase}}</p>

<!--轉換成小寫-->
<p>{{str | lowercase}}</p>

2. 日期格式轉換

<p>
{{today | date:'yyyy-MM-dd HH:mm:ss' }}
</p> 

3. 小數(shù)位數(shù)

接收的參數(shù)格式為{最少整數(shù)位數(shù)}.{最少小數(shù)位數(shù)}-{最多小數(shù)位數(shù)}

<!--保留2~4位小數(shù)-->

<p>{{p | number:'1.2-4'}}</p> 

4. JavaScript 對象序列化

<p>
    {{ { name: 'semlinker' } | json }}
</p> 
<!-- Output: { "name": "semlinker" } -->

5. slice

<p>{{ 'semlinker' | slice:0:3 }}</p> 
<!-- Output: sem -->

6. 管道鏈

<p>
{{ 'semlinker' | slice:0:3 | uppercase }}
</p> 

<!-- Output: SEM -->

7. 自定義管道

自定義管道的步驟:

  • 使用 @Pipe 裝飾器定義 Pipemetadata 信息,如 Pipe 的名稱 - 即 name 屬性
  • 實現(xiàn) PipeTransform 接口中定義的 transform 方法

7.1 WelcomePipe 定義

import { Pipe, PipeTransform } from '@angular/core';

[@Pipe](/user/Pipe)({ name: 'welcome' })

export class WelcomePipe implements PipeTransform {
  transform(value: string): string {
    if(!value) return value;
    if(typeof value !== 'string') {
      throw new Error('Invalid pipe argument for WelcomePipe');
    }
    return "Welcome to " + value;
  }
} 

7.2 WelcomePipe 使用

<div>
   <p ngNonBindable>{{ 'semlinker' | welcome }}</p>
   <p>{{ 'semlinker' | welcome }}</p> <!-- Output: Welcome to semlinker -->
</div>

7.3 RepeatPipe 定義

import {Pipe, PipeTransform} from '@angular/core';

[@Pipe](/user/Pipe)({name: 'repeat'})
export class RepeatPipe implements PipeTransform {
    transform(value: any, times: number) {
        return value.repeat(times);
    }
}

7.4 RepeatPipe 使用

<div>
   <p ngNonBindable>
   {{ 'lo' | repeat:3 }}
   </p>
   <p>
    {{ 'lo' | repeat:3 }}
   </p> 
   <!-- Output: lololo -->
</div>

3.13 實現(xiàn)一個人員登記表單-案例

image
# 創(chuàng)建組件
ng g component components/form

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

@Component({
  selector: 'app-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {

  public peopleInfo:any = {
    username: '',
    sex: '2',
    cityList: ['北京', '上海', '深圳'],
    city: '上海',

    hobby:[{
          title: '吃飯',
          checked:false
      },{
            title:'睡覺',
            checked:false
        },{

          title:'敲代碼',
          checked:true
      }],

      mark:''
  }

  constructor() { }

  ngOnInit() {

  }
  doSubmit(){
    /*    
    jquery  dom操作
      <input type="text" id="username" />
      let usernameDom:any=document.getElementById('username');
      console.log(usernameDom.value);    
    */

    console.log(this.peopleInfo);
  }
}

<h2>人員登記系統(tǒng)</h2>

<div class="people_list">
  <ul>
    <li>姓 名:<input type="text" id="username" [(ngModel)]="peopleInfo.username" value="fonm_input" /></li>
    <li>性 別:
      <input type="radio" value="1" name="sex" id="sex1" [(ngModel)]="peopleInfo.sex"> <label for="sex1">男 </label>   
      <input type="radio" value="2" name="sex"  id="sex2" [(ngModel)]="peopleInfo.sex"> <label for="sex2">女 </label>
    </li>
   <li>
    城 市:
      <select name="city" id="city" [(ngModel)]="peopleInfo.city">
          <option [value]="item" *ngFor="let item of peopleInfo.cityList">{{item}}</option>
      </select>
    </li>
    <li>
        愛 好:
        <span *ngFor="let item of peopleInfo.hobby;let key=index;">
            <input type="checkbox"  [id]="'check'+key" [(ngModel)]="item.checked"/> <label [for]="'check'+key"> {{item.title}}</label>
            &nbsp;&nbsp;
        </span>
     </li>
     <li>
       備 注:
       <textarea name="mark" id="mark" cols="30" rows="10" [(ngModel)]="peopleInfo.mark"></textarea>
     </li>
  </ul>

  <button (click)="doSubmit()" class="submit">獲取表單的內容</button>
  <br>
  <br>
  <br>
  <br>

  <pre>
    {{peopleInfo | json}}
  </pre>
</div>

h2{
    text-align: center;
}
.people_list{
    width: 400px;
    margin: 40px auto;
    padding:20px;
    border:1px solid #eee;
    li{
        height: 50px;
        line-height: 50px;
        .fonm_input{
            width: 300px;
            height: 28px;
        }
    }

    .submit{
        width: 100px;
        height: 30px;
        float: right;
        margin-right: 50px;
        margin-top:120px;
    }
}

3.14 實現(xiàn)一個完整的ToDo-案例

image

基礎版

# 創(chuàng)建組件
ng g component components/todo

<h2>todoList</h2>
<div class="todolist">
    <input class="form_input" type="text" [(ngModel)]="keyword" (keyup)="doAdd($event)" />
    <hr>
    <h3>待辦事項</h3>
    <ul>
      <li *ngFor="let item of todolist;let key=index;" [hidden]="item.status==1">
       <input type="checkbox" [(ngModel)]="item.status" />  {{item.title}}   ------ <button (click)="deleteData(key)">X</button>
      </li>
    </ul>
    <h3>已完成事項</h3>
    <ul>
        <li *ngFor="let item of todolist;let key=index;" [hidden]="item.status==0">
         <input type="checkbox" [(ngModel)]="item.status" />  {{item.title}}   ------ <button (click)="deleteData(key)">X</button>
        </li>
      </ul>
</div>

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

@Component({
  selector: 'app-todo',
  templateUrl: './todo.component.html',
  styleUrls: ['./todo.component.scss']
})
export class TodoComponent implements OnInit {

  public keyword: string;

  public todolist: any[] = [];

  constructor() { }

  ngOnInit() {
  }
  doAdd(e){
    if(e.keyCode == 13){
        if(!this.todolistHasKeyword(this.todolist, this.keyword)){
          this.todolist.push({
            title: this.keyword,
            status: 0                   //0表示代辦事項  1表示已完成事項
          });
          this.keyword='';
        }else{
          alert('數(shù)據(jù)已經(jīng)存在');
          this.keyword='';
        }
     }
  }

  deleteData(key){
    this.todolist.splice(key,1);
  }

  //如果數(shù)組里面有keyword返回true  否則返回false
  todolistHasKeyword(todolist:any, keyword:any){
    //異步  會存在問題
    // todolist.forEach(value => {

    //   if(value.title==keyword){

    //       return true;
    //   } 
    // });
    if(!keyword)  return false;

    for(var i=0; i<todolist.length; i++){
      if(todolist[i].title==keyword){
          return true;
      } 
    }
    return false;
  }

}


h2{
    text-align: center;
}
.todolist{

    width: 400px;
    margin: 20px auto;
    .form_input{

        margin-bottom: 20px;

        width: 300px;
        height: 32px;
    }

    li{

        line-height: 60px;
    }

}

3.15 搜索緩存數(shù)據(jù)-案例

基礎版

# 創(chuàng)建組件
ng g component components/search

<div class="search">
    <input type="text" [(ngModel)]="keyword" />  <button (click)="doSearch()">搜索</button>
    <hr>
    <ul>
      <li *ngFor="let item of historyList;let key=index;">{{item}}   ------ <button (click)="deleteHistroy(key)">X</button></li>
    </ul>
</div>

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

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss']
})
export class SearchComponent implements OnInit {
  public keyword: string;
  public historyList: any[] = [];

  constructor() { }
  ngOnInit() {
  }
  doSearch(){
    if(this.historyList.indexOf(this.keyword)==-1){
      this.historyList.push(this.keyword);
    }
    this.keyword = '';    
  }
  deleteHistroy(key){
      alert(key);
      this.historyList.splice(key,1);
  }
}

.search{

    width: 400px;
    margin: 20px auto;
    input{

        margin-bottom: 20px;

        width: 300px;
        height: 32px;
    }

    button{
        height: 32px;
        width: 80px;
    }
}

四错沽、Angular 中的服務

4.1 服務

定義公共的方法簿晓,使得方法在組件之間共享調用

image

1. 創(chuàng)建服務命令

ng g service my-new-service

# 創(chuàng)建到指定目錄下面
ng g service services/storage

2. app.module.ts 里面引入創(chuàng)建的服務

// app.module.ts 里面引入創(chuàng)建的服務

import { StorageService } from './services/storage.service';

// NgModule 里面的 providers 里面依賴注入服務

NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    FooterComponent,
    NewsComponent,
    TodolistComponent
], imports: [
    BrowserModule,
FormsModule
  ],
  providers: [StorageService],
  bootstrap: [AppComponent]
})
export class AppModule { }

3. 使用的頁面引入服務,注冊服務

 import { StorageService } from '../../services/storage.service';

 constructor(private storage: StorageService) {

 }

// 使用

addData(){
     // alert(this.username);
    this.list.push(this.username); 
    this.storage.set('todolist',this.list);
}
removerData(key){
    console.log(key); 
    this.list.splice(key,1); 
    this.storage.set('todolist',this.list);
}

4.2 改造上面的Todo千埃、searchList

searchList

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

// 引入服務
import { StorageService } from '../../services/storage.service';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss']
})
export class SearchComponent implements OnInit {

  public keyword: string;
  public historyList: any[] = [];

  constructor(public storage: StorageService) {
    console.log(this.storage.get());
   }

  ngOnInit() {
   // 修改的地方
    var searchlist:any=this.storage.get('searchlist');
    if(searchlist){
      this.historyList=searchlist;        
    }
  }

  doSearch(){
    if(this.historyList.indexOf(this.keyword)==-1){
      this.historyList.push(this.keyword);

      // 修改的地方
      this.storage.set('searchlist',this.historyList);
    }
    this.keyword = '';    
  }

  deleteHistroy(key){
      alert(key);
      this.historyList.splice(key,1);
  }

}

TODOLIST

  ngOnInit() {
  // 修改的地方
    var todolist:any=this.storage.get('todolist');

    if(todolist){
      this.todolist=todolist;        
    }
 }
doAdd(e){
    if(e.keyCode==13){
        if(!this.todolistHasKeyword(this.todolist,this.keyword)){
          this.todolist.push({
            title:this.keyword,
            status:0                   //0表示代辦事項  1表示已完成事項
          });
          this.keyword='';

          // 修改的地方
          this.storage.set('todolist',this.todolist);          //用到this一定要注意this指向
        }else{
          alert('數(shù)據(jù)已經(jīng)存在');
          this.keyword='';
        }
     }
  }
 // 修改的地方
checkboxChange(){
    console.log('事件觸發(fā)了');

    this.storage.set('todolist',this.todolist); 
  }

<h2>todoList</h2>
<div class="todolist">
    <input class="form_input" type="text" [(ngModel)]="keyword" (keyup)="doAdd($event)" />
    <hr>
    <h3>待辦事項</h3>
    <ul>
      <li *ngFor="let item of todolist;let key=index;" [hidden]="item.status==1">
      <!-- add checkboxChange-->
       <input type="checkbox" [(ngModel)]="item.status"  (change)="checkboxChange()"/>  {{item.title}}   ------ <button (click)="deleteData(key)">X</button>
      </li>
    </ul>
    <h3>已完成事項</h3>
    <ul>
        <li *ngFor="let item of todolist;let key=index;" [hidden]="item.status==0">
   <!-- add checkboxChange-->
         <input type="checkbox" [(ngModel)]="item.status" (change)="checkboxChange()" />  {{item.title}}   ------ <button (click)="deleteData(key)">X</button>
        </li>
      </ul>
</div>

五憔儿、Dom 操作以及@ViewChild、 執(zhí)行 css3 動畫

1. Angular 中的 dom 操作(原生 js)

ngAfterViewInit(){
var boxDom:any=document.getElementById('box'); boxDom.style.color='red';
}

2. Angular 中的 dom 操作(ViewChild)

 import { Component ,ViewChild,ElementRef} from '@angular/core';

 @ViewChild('myattr') myattr: ElementRef;

<div #myattr></div>

ngAfterViewInit(){
let attrEl = this.myattr.nativeElement;
}

image

3. 父子組件中通過 ViewChild 調用子組件 的方法

調用子組件給子組件定義一個名稱

<app-footer #footerChild></app-footer>

引入 ViewChild

 import { Component, OnInit ,ViewChild} from '@angular/core';

ViewChild 和剛才的子組件關聯(lián)起來

 @ViewChild('footerChild') footer

在父組件中調用子組件方法

 run(){ 
    this.footer.footerRun();
}

六放可、Angular 父子組件以及組件之間通訊

image

6.1 父組件給子組件傳值-@input

父組件不僅可以給子組件傳遞簡單的數(shù)據(jù)谒臼,還可把自己的方法以及整個父組件傳給子組件

1. 父組件調用子組件的時候傳入數(shù)據(jù)

<app-header [msg]="msg"></app-header>

2. 子組件引入 Input 模塊

import { Component, OnInit ,Input } from '@angular/core';

3. 子組件中 @Input 接收父組件傳過來的數(shù)據(jù)

export class HeaderComponent implements OnInit {
  @Input() msg:string

  constructor() { }

  ngOnInit() {
  }
}

4. 子組件中使用父組件的數(shù)據(jù)

<p>
  child works!
  {{msg}}
</p>

5. 把整個父組件傳給子組件

通過this傳遞整個組件實例

<app-header [home]="this"></app-header>

export class HeaderComponent implements OnInit {
  @Input() home:any

  constructor() { }

  ngOnInit() {
  }
}

執(zhí)行父組件方法 this.home.xxx()

6.2 子組件通過@Output 觸發(fā)父組件的方法(了解)

1. 子組件引入 Output 和 EventEmitter

 import { Component, OnInit ,Input,Output,EventEmitter} from '@angular/core';

2. 子組件中實例化 EventEmitter

@Output() private outer=new EventEmitter<string>(); /*用EventEmitter和output裝飾器配合使用 <string>指定類型變量*/

3. 子組件通過 EventEmitter 對象 outer 實例廣播數(shù)據(jù)

sendParent(){
  // alert('zhixing');
  this.outer.emit('msg from child')
}

4. 父組件調用子組件的時候,定義接收事件 , outer 就是子組件的 EventEmitter 對象 outer

<!--$event就是子組件emit傳遞的數(shù)據(jù)-->
 <app-header (outer)="runParent($event)"></app-header>

5. 父組件接收到數(shù)據(jù)會調用自己的 runParent 方法耀里,這個時候就能拿到子組件的數(shù)據(jù)

//接收子組件傳遞過來的數(shù)據(jù) 
runParent(msg:string){
   alert(msg);
 }

6.3 父組件通過@ViewChild 主動獲取子組 件的數(shù)據(jù)和方法

1. 調用子組件給子組件定義一個名稱

<app-footer #footerChild></app-footer>

2. 引入 ViewChild

import { Component, OnInit ,ViewChild} from '@angular/core';

3. ViewChild 和剛才的子組件關聯(lián)起來

 @ViewChild('footerChild') footer;

4. 調用子組件

run(){ this.footer.footerRun();
}

6.4 非父子組件通訊

  • 公共的服務
  • Localstorage (推薦)
  • Cookie

七蜈缤、Angular 中的生命周期函數(shù)

7.1 Angular中的生命周期函數(shù)

官方文檔:https://www.angular.cn/guide/lifecycle-hooks

  • 生命周期函數(shù)通俗的講就是組件創(chuàng)建、組件更新冯挎、組件銷毀的時候會觸發(fā)的一系列的方法劫樟。
  • Angular 使用構造函數(shù)新建一個組件或指令后,就會按下面的順序在特定時刻調用這些 生命周期鉤子方法织堂。
  • 每個接口都有唯一的一個鉤子方法叠艳,它們的名字是由接口名再加上ng前綴構成的,比如OnInit接口的鉤子方法叫做ngOnInit.

1. 生命周期鉤子分類

基于指令與組件的區(qū)別來分類

指令與組件共有的鉤子

  • ngOnChanges
  • ngOnInit
  • ngDoCheck
  • ngOnDestroy

組件特有的鉤子

  • ngAfterContentInit
  • ngAfterContentChecked
  • ngAfterViewInit
  • ngAfterViewChecked
image

2. 生命周期鉤子的作用及調用順序

1易阳、ngOnChanges - 當數(shù)據(jù)綁定輸入屬性的值發(fā)生變化時調用
2附较、ngOnInit - 在第一次 ngOnChanges 后調用
3、ngDoCheck - 自定義的方法潦俺,用于檢測和處理值的改變
4拒课、ngAfterContentInit - 在組件內容初始化之后調用
5、ngAfterContentChecked - 組件每次檢查內容時調用
6事示、ngAfterViewInit - 組件相應的視圖初始化之后調用
7早像、ngAfterViewChecked - 組件每次檢查視圖時調用
8、ngOnDestroy - 指令銷毀前調用
3. 首次加載生命周期順序

export class LifecircleComponent {

    constructor() {

        console.log('00構造函數(shù)執(zhí)行了---除了使用簡單的值對局部變量進行初始化之外肖爵,什么都不應該做')
    }

    ngOnChanges() {

        console.log('01ngOnChages執(zhí)行了---當被綁定的輸入屬性的值發(fā)生變化時調用(父子組件傳值的時候會觸發(fā))'); 
    }

    ngOnInit() {
        console.log('02ngOnInit執(zhí)行了--- 請求數(shù)據(jù)一般放在這個里面');
    }
    ngDoCheck() {
        console.log('03ngDoCheck執(zhí)行了---檢測卢鹦,并在發(fā)生 Angular 無法或不愿意自己檢測的變化時作出反應');
    }
    ngAfterContentInit() {
        console.log('04ngAfterContentInit執(zhí)行了---當把內容投影進組件之后調用');
    }
    ngAfterContentChecked() {
        console.log('05ngAfterContentChecked執(zhí)行了---每次完成被投影組件內容的變更檢測之后調用');
    }
    ngAfterViewInit() : void {
        console.log('06 ngAfterViewInit執(zhí)行了----初始化完組件視圖及其子視圖之后調用(dom操作放在這個里面)');
    }
    ngAfterViewChecked() {
        console.log('07ngAfterViewChecked執(zhí)行了----每次做完組件視圖和子視圖的變更檢測之后調用');
    }

    ngOnDestroy() {
        console.log('08ngOnDestroy執(zhí)行了····');
    }

    //自定義方法
    changeMsg() {

        this.msg = "數(shù)據(jù)改變了";
    }
}

image

check的可以對數(shù)據(jù)做響應操作

<button (click)="changeMsg()">數(shù)據(jù)改變了</button>
<input type='text' [(ngModel)]="userInfo" />

點擊按鈕/雙向數(shù)據(jù)綁定此時觸發(fā)了以下生命周期。只要數(shù)據(jù)改變

image

可以在check做一些操作

ngDoCheck() {
        //寫一些自定義的操作

        console.log('03ngDoCheck執(zhí)行了---檢測劝堪,并在發(fā)生 Angular 無法或不愿意自己檢測的變化時作出反應');
        if(this.userinfo!==this.oldUserinfo){
            console.log(`你從${this.oldUserinfo}改成${this.userinfo}`);
            this.oldUserinfo = this.userinfo;
        }else{

            console.log("數(shù)據(jù)沒有變化");          
        }

    }

7.2 生命周期鉤子詳解

7.2.1 constructor-掌握

constructor冀自,來初始化類。Angular中的組件就是基于class類實現(xiàn)的秒啦,在Angular中熬粗,constructor用于注入依賴。組件的構造函數(shù)會在所有的生命周期鉤子之前被調用余境,它主要用于依賴注入或執(zhí)行簡單的數(shù)據(jù)初始化操作驻呐。

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

@Component({
  selector: 'my-app',
  template: `
    <h1>Welcome to Angular World</h1>
    <p>Hello {{name}}</p>
  `,
})
export class AppComponent {
  name: string = '';

  constructor(public elementRef: ElementRef) {//使用構造注入的方式注入依賴對象
    // 執(zhí)行初始化操作
    this.name = 'Semlinker'; 
  }
}

7.2.2 ngOnChanges()

Angular(重新)設置數(shù)據(jù)綁定輸入屬性時響應灌诅。該 方法接受當前和上一屬性值的 SimpleChanges 對象 當被綁定的輸入屬性的值發(fā)生變化時調用,首次調用一 定會發(fā)生在 ngOnInit()之前含末。

<!-- 父組件中 傳遞title屬性給header子組件 -->
<app-header [title]="title"></app-header>

此時改變title會觸發(fā)ngOnChanges生命周期延塑,并且也會觸發(fā)

image

7.2.3 ngOnInit()--掌握

Angular 第一次顯示數(shù)據(jù)綁定和設置指令/組件的輸入屬性之后,初始化指令/組件答渔。在第一輪 ngOnChanges() 完成之后調用关带,只調用一次≌铀海可以請求數(shù)據(jù)

  • 使用 ngOnInit() 有兩個原因:
    • 在構造函數(shù)之后馬上執(zhí)行復雜的初始化邏輯
    • Angular 設置完輸入屬性之后宋雏,對該組件進行準備。有經(jīng)驗的開發(fā)者會認同組件的構建應該很便宜和安全
import { Component, Input, OnInit } from '@angular/core';

@Component({
    selector: 'exe-child',
    template: `
     <p>父組件的名稱:{{pname}} </p>
    `
})
export class ChildComponent implements OnInit {
    @Input()
    pname: string; // 父組件的名稱

    constructor() {
        console.log('ChildComponent constructor', this.pname); 
        // Output:undefined
    }

    ngOnInit() {
        console.log('ChildComponent ngOnInit', this.pname); 
        // output: 輸入的pname值
    }
}

7.2.4 ngDoCheck()

檢測务豺,并在發(fā)生 Angular 無法或不愿意自己檢測的變 化時作出反應磨总。在每個 Angular 變更檢測周期中調用, ngOnChanges()ngOnInit()之后笼沥。

7.2.5 ngAfterContentInit()

當把內容投影進組件之后調用蚪燕。第一次 ngDoCheck() 之后調用,只調用一次

7.2.6 ngAfterContentChecked()

每次完成被投影組件內容的變更檢測之后調用奔浅。 ngAfterContentInit() 和每次 ngDoCheck() 之后調

7.2.7 ngAfterViewInit()--掌握

初始化完組件視圖及其子視圖之后調用馆纳。第一 次 ngAfterContentChecked() 之后調用,只調用一次汹桦。在這里可以操作DOM

7.2.8 ngAfterViewChecked()

每次做完組件視圖和子視圖的變更檢測之后調用鲁驶。 ngAfterViewInit()和每次 ngAfterContentChecked() 之后 調用。

7.2.9 ngOnDestroy()--掌握

Angular 每次銷毀指令/組件之前調用并清掃舞骆。在這兒反訂閱可觀察對象和分離事件處理器钥弯,以防內存泄 漏。在 Angular 銷毀指令/組件之前調用督禽。比如:移除事件監(jiān)聽脆霎、清除定時器、退訂 Observable 等狈惫。

@Directive({
    selector: '[destroyDirective]'
})
export class OnDestroyDirective implements OnDestroy {
  sayHello: number;

  constructor() {
    this.sayHiya = window.setInterval(() => console.log('hello'), 1000);
  }

  ngOnDestroy() {
     window.clearInterval(this.sayHiya);
  }
}

八睛蛛、Rxjs 異步數(shù)據(jù)流編程

8.1 Rxjs介紹

RxJSReactiveX 編程理念的 JavaScript 版本。ReactiveX 來自微軟虱岂,它是一種針對異步數(shù)據(jù) 流的編程玖院。簡單來說,它將一切數(shù)據(jù)第岖,包括 HTTP 請求,DOM 事件或者普通數(shù)據(jù)等包裝成流的形式试溯,然后用強大豐富的操作符對流進行處理蔑滓,使你能以同步編程的方式處理異步數(shù)據(jù),并組合不同的操作符來輕松優(yōu)雅的實現(xiàn)你所需要的功能。

  • RxJS 是一種針對異步數(shù)據(jù)流編程工具键袱,或者叫響應式擴展編程;可不管如何解釋 RxJS 其目 標就是異步編程燎窘,Angular 引入 RxJS 為了就是讓異步可控、更簡單蹄咖。
  • RxJS 里面提供了很多模塊褐健。這里我們主要給大家講 RxJS 里面最常用的Observable 和 fromEvent

目前常見的異步編程的幾種方法:

  • 回調函數(shù)
  • 事件監(jiān)聽/發(fā)布訂閱
  • Promise
  • Rxjs

8.2 Promise和RxJS處理異步對比

新建一個services

ng g service services/rxjs

services/rxjs.service.ts中寫以下方法

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class RxjsService {
  constructor() { }

 // Promise 處理異步
  getPromiseData() {
    return new Promise(resolve = >{
    setTimeout(() = >{
        resolve('---promise timeout---');
    },
    2000);
  });

// RxJS 處理異步:
getRxjsData() {
   return new Observable(observer = >{
      setTimeout(() = >{
        observer.next('observable timeout');
      },
      2000);
  }); 
}

}

// 在其他組件使用服務
import { Component, OnInit } from '@angular/core';
import { RxjsService } from '../../services/rxjs.service';

@Component({
  selector: 'app-rxjs',
  templateUrl: './rxjs.component.html',
  styleUrls: ['./rxjs.component.scss']
})
export class RxjsComponent implements OnInit {

  // 注入服務
  constructor(public request: RxjsService) {

   }

  ngOnInit() {
    // 調用方法
     this.request.getRxjsData().subscribe(data=>{
      console.log(data)
    })
  }

}

  • 從上面列子可以看到 RxJSPromise的基本用法非常類似,除了一些關鍵詞不同澜汤。Promise 里面用的是 then()resolve()蚜迅,而 RxJS里面用的是 next()subscribe()
  • Rxjs相比Promise要強大很多。 比如 Rxjs 中可以中途撤回俊抵、Rxjs 可以發(fā)射多個值谁不、Rxjs 提供了多種工具函數(shù)等等

8.3 Rxjs unsubscribe 取消訂閱

Promise 的創(chuàng)建之后,動作是無法撤回的徽诲。Observable 不一樣刹帕,動作可以通過 unsbscribe() 方法中途撤回,而且 Observable 在內部做了智能的處理.

Promise 創(chuàng)建之后動作無法撤回

let promise = new Promise(resolve = >{
    setTimeout(() = >{
        resolve('---promise timeout---');
    },
    2000);
});
promise.then(value = >console.log(value));

Rxjs 可以通過 unsubscribe() 可以撤回 subscribe 的動作

let stream = new Observable(observer = >{
    let timeout = setTimeout(() = >{
        clearTimeout(timeout);
        observer.next('observable timeout');
    },
    2000);
});
let disposable = stream.subscribe(value = >console.log(value));
setTimeout(() = >{
    //取消執(zhí)行 disposable.unsubscribe();
},
1000);

8.4 Rxjs 訂閱后多次執(zhí)行

  • 如果我們想讓異步里面的方法多次執(zhí)行谎替,比如下面代碼偷溺。

這一點 Promise是做不到的,對于 Promise來說钱贯,最終結果要么 resole(兌現(xiàn))亡蓉、要么 reject (拒絕),而且都只能觸發(fā)一次喷舀。如果在同一個 Promise 對象上多次調用 resolve 方法砍濒, 則會拋異常。而 Observable不一樣硫麻,它可以不斷地觸發(fā)下一個值爸邢,就像 next()這個方法的 名字所暗示的那樣。

let promise = new Promise(resolve = >{
    setInterval(() = >{
        resolve('---promise setInterval---');
    },
    2000);
});
promise.then(value = >console.log(value));

Rxjs

let stream = new Observable < number > (observer = >{
    let count = 0;
    setInterval(() = >{
        observer.next(count++);
    },
    1000);
});
stream.subscribe(value = >console.log("Observable>" + value));

8.5 Angualr6.x之前使用Rxjs的工具函數(shù) map filter

注意:Angular6 以后使用以前的rxjs 方法拿愧,必須安裝 rxjs-compat 模塊才可以使用 map杠河、filter 方法。

angular6 后官方使用的是 RXJS6的新特性浇辜,所以官方給出了一個可以暫時延緩我們不需要修 改 rsjx 代碼的辦法

npm install rxjs-compat

import {Observable} from 'rxjs'; import 'rxjs/Rx';

let stream = new Observable < any > (observer = >{
    let count = 0;
    setInterval(() = >{
        observer.next(count++);
    },
    1000);
});
stream.filter(val = >val % 2 == 0).subscribe(value = >console.log("filter>" + value));
stream.map(value = >{
    return value * value
}).subscribe(value = >console.log("map>" + value));

8.6 Angualr6.x 以后 Rxjs6.x 的變化以及 使用

8.6.1 Rxjs 的變化參考

Angular5升級到Angular6券敌, angular6相比較于angular5總體變化不大,但是在RXJS上面卻有一些變動柳洋,下面給大家講講關于Angular6版本升級和RXJS6新特性的講解

1. angular6 Angular7中使用以前的rxjs

對于寫了半年多的項目待诅,模塊已經(jīng)很多了,所以不可能在升級到angular6后馬上更新所有代碼關于RXJS6的新特性熊镣,所以官方給出了一個可以暫時延緩我們不需要修改rsjx代碼的辦法卑雁。

npm install --save rxjs-compat

  • 優(yōu)點: 暫時不用改代碼募书,可以一點點地改,直到改完后吧這個包卸掉
  • 缺點: 對于rxjs6renameoperator無效测蹲,所以莹捡,如果有用到renameAPI,必須手動修改

2. Angular6 以后 RXJS6的變化

RXJS6改變了包的結構扣甲,主要變化在 import方式和operator上面以及使用pipe()

2.1 Imports 方式改變

image

rxjs中類似像導入observable subject 等的不再進一步導入篮赢,而是止于rxjs, rxjs6在包的結構上進行了改變

2.2 operator的改變

image

總而言之: 類似于創(chuàng)建之類的用的API都是從rxjs引入的,類似于map 之類的操作都是從rxjs/operators引入的

image

2.3 pipeable observable

image

2.4 被重新命名的API

image

RXJS6 改變了包的結構琉挖,主要變化在 import 方式和 operator 上面以及使用 pipe()

import {Observable} from 'rxjs';
import {map,filter} from 'rxjs/operators';

let stream= new Observable<any>(observer => {
    let count = 0;
    setInterval(() = >{
        observer.next(count++);
    },
    1000);
});

stream.pipe(filter(val = >val % 2 == 0))
.subscribe(value = >console.log("filter>" + value));

stream
.pipe(
    filter(val = >val % 2 == 0), 
    map(value = >{
        return value * value
}))
.subscribe(value = >console.log("map>" + value));

8.7 Rxjs 延遲執(zhí)行

import {
    Observable,
    fromEvent
}
from 'rxjs';
import {
    map,
    filter,
    throttleTime
}
from 'rxjs/operators';

var button = document.querySelector('button');

fromEvent(button, 'click')
.pipe(throttleTime(1000))
.subscribe(() = >console.log(`Clicked`));

九启泣、Angular 中的數(shù)據(jù)交互(get jsonp post)

9.1 Angular get 請求數(shù)據(jù)

Angular5.x 以后 getpost 和和服務器交互使用的是 HttpClientModule 模塊粹排。

1. 在 app.module.ts 中引入 HttpClientModule 并注入

import {HttpClientModule} from '@angular/common/http';

imports: [
    BrowserModule,
    HttpClientModule
]

2. 在用到的地方引入 HttpClient 并在構造函數(shù)聲明

import {HttpClient} from "@angular/common/http";

constructor(public http:HttpClient) { }

3. get 請求數(shù)據(jù)

var api = "http://a.itying.com/api/productlist";

this.http.get(api).subscribe(response => {
console.log(response); });

9.2 Angular post 提交數(shù)據(jù)

Angular5.x 以后 get种远、post 和和服務器交互使用的是HttpClientModule 模塊。

1. 在 app.module.ts 中引入 HttpClientModule 并注入

import {HttpClientModule} from '@angular/common/http';

imports: [
    BrowserModule,
    HttpClientModule
]

2. 在用到的地方引入 HttpClient顽耳、HttpHeaders 并在構造函數(shù)聲明 HttpClient

import {HttpClient,HttpHeaders} from "@angular/common/http";

constructor(public http:HttpClient) { }
  1. post 提交數(shù)據(jù)

用express搭建一個server

// package.json
{
"dependencies": {
"ejs": "^2.5.6",
"express": "^4.15.3",
"socket.io": "^2.0.3",
"body-parser": "~1.17.1"
}
}
// app.js 代碼
var express = require('express');
var app=express();
var bodyParser = require('body-parser');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

/express允許跨域/
app.all('', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "
");
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1')
if(req.method=="OPTIONS") res.send(200);
else next();
});

//app.use(express.static(path.join(__dirname, 'public')));

app.get('/',function(req,res){
res.send('首頁');
})
app.post('/dologin',function(req,res){
console.log(req.body);
res.json({"msg":'post成功'});
})

app.get('/news',function(req,res){

//console.log(req.body);
res.jsonp({"msg":'這是新聞數(shù)據(jù)'});

})

app.listen(3000,'127.0.0.1',function(){
console.log('項目啟動在3000端口')
});
// angular代碼

doLogin() {

// 手動設置請求類型
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
var api = "http://127.0.0.1:3000/doLogin";

this.http.post(api, {
username: '張三',
age: '20'
},
httpOptions).subscribe(response = >{
console.log(response);
});
}
9.3 Angular Jsonp 請求數(shù)據(jù)

  1. 在 app.module.ts 中引入 HttpClientModule坠敷、HttpClientJsonpModule 并注入

import {HttpClientModule,HttpClientJsonpModule} from '@angular/common/http';
imports: [
BrowserModule,
HttpClientModule,
HttpClientJsonpModule
]

  1. 在用到的地方引入 HttpClient 并在構造函數(shù)聲明

import {HttpClient} from "@angular/common/http";

constructor(public http:HttpClient) { }

  1. jsonp 請求數(shù)據(jù)

// 接口支持jsonp請求
var api = "http://a.itying.com/api/productlist";

this.http.jsonp(api,'callback').subscribe(response => {
console.log(response); });
9.4 Angular 中使用第三方模塊 axios 請求數(shù)據(jù)

  1. 安裝 axios

cnpm install axios --save

  1. 用到的地方引入 axios

import axios from 'axios';

  1. 看文檔使用

axios.get('/user?ID=12345').then(function(response) {
// handle success
console.log(response);
}).
catch(function(error) {
// handle error console.log(error);
}).then(function() {
// always executed
});

十、Angular 中的路由
10.1 Angular 創(chuàng)建一個默認帶路由的項目

  1. 命令創(chuàng)建項目

ng new angualrdemo08 --skip-install

  1. 創(chuàng)建需要的組件

ng g component home
ng g component news
ng g component newscontent

  1. 找到 app-routing.module.ts 配置路由

// 引入組件

import { HomeComponent } from './home/home.component';
import { NewsComponent } from './news/news.component';
import { NewscontentComponent } from './newscontent/newscontent.component';

// 配置路由
const routes: Routes = [
{path: 'home', component: HomeComponent},
{path: 'news', component: NewsComponent},
{path: 'newscontent/:id', component: NewscontentComponent},
{
path: '',
redirectTo: '/home',
pathMatch: 'full'
} ];

  1. 找到 app.component.html 根組件模板射富,配置 router-outlet 顯示動態(tài)加載的路由

<h1>
<a routerLink="/home">首頁</a> <a routerLink="/news">新聞</a>
</h1>
<router-outlet></router-outlet>
10.2 routerLink 跳轉頁面 默認路由
<a routerLink="/home">首頁</a>
<a routerLink="/news">新聞</a>
//匹配不到路由的時候加載的組件 或者跳轉的路由
{
path: '', /任意的路由/
// component:HomeComponent
redirectTo:'home'
}
10.3 routerLinkActive 設置routerLink 默認選中路由
<h1>
<a routerLink="/home" routerLinkActive="active">首頁</a> <a routerLink="/news" routerLinkActive="active">新聞</a>
</h1>
<h1>
<a [routerLink]="[ '/home' ]" routerLinkActive="active">首頁</a> <a [routerLink]="[ '/news' ]" routerLinkActive="active">新聞</a>
</h1>
.active{
color:red;
}
10.4 routerLink Get傳遞參數(shù)

  1. 跳轉

<li *ngFor="let item of list;let key=index;">

  <a [routerLink]="['/news-detail']" [queryParams]="{aid:key}">{{key}}--{{item}}</a>

</li>
  1. 接收參數(shù)

    import { ActivatedRoute } from '@angular/router';

    constructor(public route:ActivatedRoute) { }

    this.route.queryParams.subscribe((data)=>{
    console.log(data);
    })
    10.5 動態(tài)路由
    1.配置動態(tài)路由

const routes: Routes = [
{path: 'home', component: HomeComponent},
{path: 'news', component: NewsComponent},
{path: 'newscontent/:id', component: NewscontentComponent},
{
path: '',
redirectTo: '/home',
pathMatch: 'full'
} ];

  1. 跳轉傳值

<a [routerLink]="[ '/newscontent/',aid]">跳轉到詳情</a>
<a routerLink="/newscontent/{{aid}}">跳轉到詳情</a>

  1. 獲取動態(tài)路由的值

import { ActivatedRoute} from '@angular/router';

constructor( private route: ActivatedRoute) { }

ngOnInit() {
console.log(this.route.params);
this.route.params.subscribe(data=>this.id=data.id);
}
10.6 動態(tài)路由的 js 跳轉
// 引入
import { Router } from '@angular/router';

// 初始化

export class HomeComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {}
goNews(){
// this.router.navigate(['/news', hero.id]);
this.router.navigate(['/news']);
}
}
// 路由跳轉
this.router.navigate(['/news', hero.id]);
10.7 路由 get 傳值 js 跳轉

  1. 引入 NavigationExtras

import { Router ,NavigationExtras} from '@angular/router';

  1. 定義一個 goNewsContent 方法執(zhí)行跳轉膝迎,用 NavigationExtras 配置傳參。

goNewsContent() {
let navigationExtras: NavigationExtras = {
queryParams: {
'session_id': '123'
},
fragment: 'anchor'
};
this.router.navigate(['/news'], navigationExtras);
}

  1. 獲取 get 傳值

constructor(private route: ActivatedRoute) {
console.log(this.route.queryParams);
}
10.8 父子路由

  1. 創(chuàng)建組件引入組件

import { NewsaddComponent } from './components/newsadd/newsadd.component';
import { NewslistComponent } from './components/newslist/newslist.component';

  1. 配置路由

{
path: 'news',
component: NewsComponent,
children: [{
path: 'newslist',
component: NewslistComponent
},
{
path: 'newsadd',
component: NewsaddComponent
}]
}

  1. 父組件中定義 router-outlet

<router-outlet></router-outlet>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末胰耗,一起剝皮案震驚了整個濱河市限次,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌柴灯,老刑警劉巖卖漫,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異赠群,居然都是意外死亡羊始,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門查描,熙熙樓的掌柜王于貴愁眉苦臉地迎上來突委,“玉大人,你說我怎么就攤上這事冬三≡扔停” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵勾笆,是天一觀的道長敌蚜。 經(jīng)常有香客問我,道長匠襟,這世上最難降的妖魔是什么钝侠? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任该园,我火速辦了婚禮酸舍,結果婚禮上帅韧,老公的妹妹穿的比我還像新娘。我一直安慰自己啃勉,他們只是感情好忽舟,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著淮阐,像睡著了一般叮阅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泣特,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天浩姥,我揣著相機與錄音,去河邊找鬼状您。 笑死勒叠,一個胖子當著我的面吹牛,可吹牛的內容都是我干的膏孟。 我是一名探鬼主播眯分,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼柒桑!你這毒婦竟也來了弊决?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤魁淳,失蹤者是張志新(化名)和其女友劉穎飘诗,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體界逛,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡昆稿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了仇奶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片貌嫡。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖该溯,靈堂內的尸體忽然破棺而出岛抄,到底是詐尸還是另有隱情,我是刑警寧澤狈茉,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布夫椭,位于F島的核電站,受9級特大地震影響氯庆,放射性物質發(fā)生泄漏蹭秋。R本人自食惡果不足惜扰付,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仁讨。 院中可真熱鬧羽莺,春花似錦、人聲如沸洞豁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丈挟。三九已至刁卜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間曙咽,已是汗流浹背蛔趴。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留例朱,地道東北人孝情。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像茉继,于是被迫代替她去往敵國和親咧叭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359