安裝angular的命令行工具
npm i -g @angular/cli
安裝完后執行以下命令創建新項目:
ng new 項目名
然后進入項目目錄
cd 項目名
啟動開發環境
ng server
快速創建組件(並自動在app.module.ts中導入)
ng g c 組件名
屬性綁定
[屬性名]="表達式"
如果不加[] 那""里面的就會被當前字符串
如[bgColor]="'red'"等同於 bgColor="red"
如果[bgColor]="red" 這樣寫, 那編譯器會找不到red這個變量
class綁定
[ngClass]="{xxx: 表達式, ... }" 表達式為真則元素就有xxx這個class
style綁定
注意css屬性名是駝峰式
[ngStyle]="{backgroundColor: isRed ? 'red' : 'green'}"
條件渲染
*ngIf="表達式"
*ngIf="表達式; else 元素引用名稱"
<xxx #名稱 >
<div [ngSwitch]="..."> <div *ngSwitchCase="..."> </div> </div>
循環渲染
*ngFor="let item of list"
注意:同一個元素只能有一個*指令
服務類組件
用於封裝可復用的業務邏輯代碼
一般命名為 xxx.service.ts
創建服務:
import { Injectable } from '@angular/core'; @Injectable() export class HelloService { printHello(): void { console.log('hello'); } }
在app.module.ts中注冊一個provider:
//引入HelloService
import {HelloService} from './hello.service';
//在構造函數中進行依賴注入 @NgModule({ ... providers: [HelloService], ... })
在需要用到的頁面引入該服務:
import {HelloService} from './hello.service'; //在構造函數中進行依賴注入 constructor(private helloService: HelloService) {...} //調用服務組件的方法 this.helloService.printHello();
- 服務都是單例的,一旦創建就會被緩存起來 重復使用
- 服務一旦實例化,將在整個應用的生命周期中存在,可以用來共享數據(下面axios部分有實例)
- 在需要使用服務的地方,利用依賴注入機制注入服務
- 依賴注入時自定義的服務需要寫在內置的服務后面
父組件 向 子組件 傳數據
<sub-component [propName]="value" >
綁定事件監聽
<div (click)="myFunction($event)" >
在組件ts文件內定義myFunction方法,其可接收到$event事件對象
自定義事件
<sub-component (myEvent)="doSomething()">
在子組件中,引入EventEmitter,
import {EventEmitter} from "@angular/core";
子組件先聲明事件對象
@Output() myEvent = new EventEmitter<boolean>();
子組件的某個方法里調用
this.myEvent.emit(agreed);
解決跨級組件通信
1 創建服務,new一個EventEmitter
import {Injectable, EventEmitter, OnInit} from "@angular/core"; @Injectable() export class EmitService implements OnInit { public eventEmit: any; constructor() { // 定義發射事件 this.eventEmit = new EventEmitter(); } ngOnInit() { } }
2、配置module.ts
import {BrowserModule} from '@angular/platform-browser'; import {NgModule} from '@angular/core'; import {AppComponent} from './app.component'; import {EmitComponent} from "./emit.component"; import {EmitService} from "./emit.service"; @NgModule({ declarations: [ AppComponent, EmitComponent ], imports: [ BrowserModule ], providers: [ EmitService ], bootstrap: [ AppComponent ] }) export class AppModule { }
3、定義組件,發射消息
import {Component} from '@angular/core'; import {EmitService} from "./emit.service" @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { constructor(public emitService: EmitService) { } emitFun() { // 如果組件中,修改了某些數據,需要刷新用用戶列表,用戶列表在其他組件中,那么就可以發射一個字符串過去,那邊接收到這個字符串比對一下,刷新列表。 this.emitService.eventEmit.emit("userList"); } }
4、定義接收組件,接收比對發射的字符串,判斷,調取接口,刷新組件內容
import {Component, OnInit} from "@angular/core"; import {EmitService} from "./emit.service" @Component({ selector: "event-emit", templateUrl: "./emit.component.html" }) export class EmitComonent implements OnInit { constructor(public emitService: EmitService) { } ngOnInit() { // 接收發射過來的數據 this.emitService.eventEmit.subscribe((value: any) => { if(value == "userList") { // 這里就可以調取接口,刷新userList列表數據 alert("收到了,我立馬刷新列表"); } }); } }
總結:其實就是EventEmitter的兩個方法,emit(),subscribe()發射和接收;
對象本地指向
(如果是input元素,其類型是HTMLInputElemet)
<div #oneElement > <div (click)="func(oneElement)" >
import {ElementRef, ViewChild, ContentChild} from 'angular/core'; //通過 @ViewChild 引用 當前組件模板中的#名稱的dom元素 @ViewChild('名稱') 變量名: ElementRef //通過 @ContentChild 引用 父組件中子組件的子元素#名稱的dom元素 @ContentChild('名稱') 變量名: ElementRef
內容分發(類似Vue的slot)
子組件利用<ng-content></ng-content> 引用 父組件中此組件標簽的子元素.
生命周期
init之前會調constructor()
ngOnChanges(change: SimpleChanges) ;需要import {SimpleChanges } from '@angular/core';
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
ngOnDestroy
class xxx implements OnInit, OnChanges
自定義指令
@Directive({ selector: '[指令名]' }) export class 類名 implements OnInit { constructor(private elementRef: ElementRef, renderer: Renderer2) { } ngOnInit() {
this.renderer.setStyle(this.elementRef.nativeElement, 'background-color', 'red');
} }
構造函數的參數elementRef就是調用這個指令的元素,前面應該加上private,否則在類中其它方法中引用this.el時會報錯
調用時就是在元素中用上面的指令名做為屬性名, 不需要加[]或*,
使用之前還要在ngModule的declarations中聲明(官方文檔里居然沒有寫這部分)
@ngModule({
declarations: {
指令類名
}
})
我用ionic g d 指令名 這個命令生成的指令, 它自動生成了"directives"文件夾,其下生成了 directives.module.ts 和 "指令名/指令名.directive.ts", directives.module.ts 內容如下:
import { NgModule } from '@angular/core'; import { HightLightDirective } from './hight-light/hight-light'; @NgModule({ declarations: [HightLightDirective], imports: [], exports: [HightLightDirective] }) export class DirectivesModule {}
同時,如果使用 directives.module.ts , 那么,在app.module.ts中也可以這樣引用並聲明指令:
import { DirectivesModule } from '../directives/directives.module'; @NgModule({ ... //導入 模塊 imports: [ DirectivesModule, ... ], ... })
用命令行工具創建指令
ng g d 路徑/my-name
指令文件名小寫以-連接,生成文件名為my-name.directive.ts,
生成的指令類名為MyNameDirectvie, 選擇器名為appMyName,
在指令類中,通過@hostlistener監聽事件
import {HostListener} from '@angular/core';
@HostListener('mouseenter') dosomething(event: Event) {}
在指令類中,通過@HostBinding綁定屬性,將指令內的變量綁定到引用元素上的屬性值
import {HostBinding} from '@angular/core';
@HostBinding('style.backgroundColor') bgc:strind = 'red';
還可以通過引用元素的屬性向指令傳遞參數,方法與經組件傳參數一樣,用@input()
路由
1.在app-routing.module.ts中引用路由模塊
(*以下代碼,在使用ng new 創建項目時如果選擇了使用路由,那么將會自動創建)
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = []; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
2.引入組件
在根模塊中引入和聲明組件, (如果是通過命令創建的組件,則工具會自動完成這步)
在app-routing.module.ts中引入組件
import { MyComponent } from "path/to/MyComponent";
3.定義路由規則
const routes: Routes = [ {path: 'path1', component: MyComponent1}, {path: 'path2', component: MyComponent2}, .... ];
path如果以/開頭就是絕對路徑,指向網站根路徑,即http://domain/, 否則就是相對路徑,相對於當前 定義路由的模塊的路徑.
比如在 app-routing.module.ts 中定義了一條path: news, 訪問時就是 http://domain/news
*在瀏覽器中訪問時路徑區分大小寫
在根組件模板中添加"路由出口",即在HTML中路由動態加載組件的地方
<router-outlet></router-outlet>
默認路由
{path: '**', component: HomeComponent}
或
{path: '**', redirectTo: 'home'}
'**'表示匹配任意路徑,(實測發現 '' 也可以)
注意,這個默認路由規則 必須 寫在后面,如果寫在前面,那其它規則就都失效了
創建跳轉鏈接, 在一個標簽中使用
[routerLink]="[ '/news' ]"
路徑如果是相對路徑,則是相對當前的url,
當前激活路由,給他一個類用來指定激活路由的樣式
routerLinkActive="active"
路由傳參
get方式
//在html中跳轉連接上加上 [queryParams]="{id:123}" //跳轉的目標組件引入 import { ActivatedRoute } from '@angular/router'; //目標組件聲明
constructor(public route: ActivatedRoute) {}
//接收參數
this.route.queryParams.subscribe((data)=>{
console.log(data); // {id: 123}
})
動態路由
//定義路由規則 , 只要在path的值中加入:參數名就可以了 {path: 'home/:id', component: HomeComponent} //定義連接 [routerLink]="['/path/', id]" //目標組件中仍然要引入ActivatedRoute import {ActivatedRoute} from '@angular/router'; //在構造函數中聲明 constructor(public route: ActivatedRoute) {} //接收參數,與get傳參唯一不同的是.params this.route.params.subscribe((data) => { console.log(data); //{id: xxx} });
//官方文檔中是這樣寫的: (paramMap和params有什么區別?)
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
編程方式路由跳轉
在JS代碼中用路由的API進行跳轉, 上面的跳轉都是通過html中添加[routerLink]屬性
編程路由跳轉也分為GET傳值和 動態路由 兩種方式
編程式動態路由跳轉:
//同樣需要在路由規則中配置動態路由規則 {path: 'home/:id', component: HomeComponent} //在要調用路由跳轉API的組件中引入路由模塊 import {Router} from '@angular/router'; //在構造函數上聲明 contructor(public router: Router) {} //調用, navigate的第一個參數是一個數組 this.router.navigate(['/path', param]); //接收 this.route.params.subscribe((data) => { console.log('在news頁中接收到',data); // {id: 123} })
編程式GET傳參路由跳轉
//引入 import { Router, NavigationExtras } from '@angular/router'; //定義路由參數 let navigationExtras: NavigationExtras = { queryParams: {id: 123}, fragment: 'anchor' } this.router.navigate(['/path'], navigationExtras); //接收 this.route.queryParams.subscribe((data) => { console.log('在news頁中接收到',data); // {id: 123} });
父子路由/嵌套路由
//在路由規則中定義子中由 const routes: Routes = [ { path: '...',component: ..., children: [ {path: ..., component: ...}, ... ] }, ]
//跳轉 <a [routerLink]="['/path/to']" ></a> //或 <a [routerLink]="['to']" ></a>
//在父組件中加入 組件模板出口 <router-outlet></router-outlet>
HTTP數據請求
GET請求
1.在app.module.ts引入HttpClientModule .
import {HttpClientModule} from '@aunglar/common/http';
imports: [..., HttpClientModule, ...]
2.在用到的地方引入
import {HttpClient} from '@angular/common/http';
並在構造函數聲明
constructor(public http: HttpClient) {}
3.使用get請求數據
this.http.get(url).subscribe((response)=>{});
POST請求
1.在app.module.ts引入HttpClientModule .與上面一樣(略)
2.在用到的地方引入
import {HttpClient, HttpHeaders} from '@angular/common/http';
3.定義http請求選項
const httpOptions = { headers: new HttpHeaders({'Content-Type', 'application/json'}); };
4.調用post請求
this.http.post(url, {...}, httpOptions).subscribe((response)=>{});
JSONP請求
1.在app.module.ts引入HttpClientModule 和 HttpClientJsonpModule
import { HttpClientModule, HttpClientJsonpModule } from '@aunglar/common/http';
imports: [..., HttpClientModule, HttpClientJsonpModule, ...]
2.在用到的地方引用HttpClientModule,(同get請求,略)
並在構造函數聲明
3.使用get請求數據
this.http.jsonp(url, 'callback').subscribe((response)=>{});
注: 第二個參數根據實際服務器的情況設置,可以通過在瀏覽器地址欄直接訪問接口地址,觀察返回結果,如果開頭是callback就寫callback,是什么第二個參數就寫什么
另:http也提供了put,delete 方法
使用axios請求數據
安裝
npm i axios -S
可以新建一個服務, 如果不用服務封裝,也可以直接在使用的組件中直接引入axios並使用
ng g service service/http
在其中引入
import axios from 'axios';
調用
axiosGet(url) {
return new Promise((resolve, reject)=>{
axios.get(url).then((response)=>{ resolve(response); });
});
}
在app.module.ts中引入服務
import httpService from './service/httpservice.service';
並在providers中聲明
providers: [..., httpService, ...]
在使用服務的文件中也要引入服務 (略)
在構造函數的參數中聲明服務對象
constructor(...,public httpService: HttpService) {}
調用
this.httpService.axiosGet(url).then(...)