欧美亚洲韩国_av电影院在线看_久久久久97_台湾佬中文娱乐网欧美电影

站長資訊網
最全最豐富的資訊網站

深入了解Angular(新手入門指南)

本篇文章帶大家深入了解Angular,分享最全的Angular新手入門指南,希望對大家有所幫助!

深入了解Angular(新手入門指南)

前端(vue)入門到精通課程,老師在線輔導:聯系老師
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調試工具:點擊使用

Angular概述

Angular 是谷歌開發的一款開源的 web 前端框架,基于 TypeScript 。【相關教程推薦:《angular教程》】

和 react 與 vue 相比, Angular 更適合中大型企業級項目。

Angular程序架構

深入了解Angular(新手入門指南)

Angular優勢

  • 可伸縮性:基于RxJS 、immutable.js和其他推送模型,能適應海量數據需求
  • 跨平臺:漸進式應用(高性能、離線使用、免安裝),原生(Ionic),桌面端
  • 生產率:模版(通過簡單而強大的模版語法,快速創建UI視圖),CLI(快速進入構建環節、添加組件和測試,然后立即部署)
  • 測試:單元測試(支持Karma、Jasmine等工具進行單元測試),端到端測試(支持Protractor等工具進行端到端測試)

@angular/cli腳手架

ng new 新建項目

  • ——routing 配置路由
  • ——style=css|scss|less 配置css樣式

ng serve 啟動項目

  • ——port 4200 端口號,默認4200
  • ——open 自動打開瀏覽器

ng build 打包項目

  • ——aot 預編譯
  • ——prod 壓縮打包
  • ——base-href=/static/

ng generate 創建模塊/組件/服務

  • module ——routing 創建模塊
  • component 創建組件
  • service / 創建服務

文件加載順序

main.ts => app.module.ts => app.component.ts => index.html => app.component.html

項目目錄結構

|-- project 	|-- .editorconfig // 用于在不同編輯器中統一代碼風格 	|-- .gitignore // git中的忽略文件列表 	|-- README.md // markdown格式的說明文件 	|-- angular.json // angular的配置文件 	|-- browserslist // 用于配置瀏覽器兼容性的文件 	|-- karma.conf.js // 自動化測試框架Karma的配置文件 	|-- package-lock.json // 依賴包版本鎖定文件 	|-- package.json // npm的包定義文件 	|-- tsconfig.app.json // 用于app項目的ts配置文件 	|-- tsconfig.json // 整個工作區的ts配置文件 	|-- tsconfig.spec.json // 用于測試的ts配置文件 	|-- tslint.json // ts的代碼靜態掃描配置 	|-- e2e // 自動化集成測試目錄 	|-- src // 源代碼目錄   |-- src // 源代碼目錄 	|-- favicon.ico // 收藏圖標 	|-- index.html // 單頁應用到宿主HTML 	|-- main.ts // 入口 ts 文件 	|-- polyfills.ts // 用于不同瀏覽器的兼容腳本加載 	|-- styles.css // 整個項目的全局css 	|-- test.ts // 測試入口 	|-- app // 工程源碼目錄 	|-- assets // 資源目錄 	|-- environments // 環境配置 		|-- environments.prod.ts // 生產環境 		|-- environments.ts // 開發環境
登錄后復制

Angular模塊

在 app.module.ts 中定義 AppModule,這個根模塊會告訴 Angular 如何組裝應用。

深入了解Angular(新手入門指南)

@NgModule 裝飾器

@NgModule 接受一個元數據對象,告訴 Angular 如何編譯和啟動應用

設計意圖

  • 靜態的元數據(declarations)
  • 運行時的元數據(providers)
  • 組合與分組(imports 和 exports)

元數據

  • declarations 數組:模塊擁有的組件、指令或管道,注意每個組件/指令/管道只能在一個模塊中聲明
  • providers 數組: 模塊中需要使用的服務
  • imports 數組:導入本模塊需要的依賴模塊,注意是模塊
  • exports 數組: 暴露給其他模塊使用的組件、指令或管道等
  • bootstrap 數組:指定應用的主視圖(稱為根組件)通過引導根 AppModule 來啟動應用,即項目剛加載時選擇讀哪個組件
  • entryComponents 數組:一般用于動態組件

內置模塊

常用的有:核心模塊、通用模塊、表單模塊、網絡模塊等

深入了解Angular(新手入門指南)

自定義模塊

當項目比較小的時候可以不用自定義模塊

但是當項目非常龐大的時候,把所有的組件都掛載到根模塊里面就不太合適了

所以可以使用自定義模塊來組織項目,并且通過自定義模塊可以實現路由的懶加載

模塊的tips

導入其他模塊時,需要知道使用該模塊的目的

  • 如果是組件,那么需要在每一個需要的模塊中都進行導入
  • 如果是服務,那么一般來說在根模塊導入一次即可

需要在每個需要的模塊中進行導入的

  • CommonModule : 提供綁定、*ngIf 和 *ngFor 等基礎指令,基本上每個模塊都需要導入它
  • FormsModule / ReactiveFormsModule : 表單模塊需要在每個需要的模塊導入
  • 提供組件、指令或管道的模塊

只在根模塊導入一次的

  • HttpClientModule / BrowerAnimationsModule NoopAnimationsModule
  • 只提供服務的模塊

Angular組件

深入了解Angular(新手入門指南)

  • 組件是 Angular 的核心,是 Angular 應用中最基本的 UI 構造塊,控制屏幕上被稱為視圖的一小片區域
  • 組件必須從屬于某個 NgModule 才能被其他組件或應用使用
  • 組件在 @NgModule 元數據的 declarations 字段中引用

@Component 元數據

  • selector :選擇器,選擇相匹配的HTML里的指令模版
  • templateUrl :將選擇器中匹配的指令同級替換成值的模版
  • template :內嵌模版,直接可以在里面寫HTML模版
  • styleUrls :對應模版的樣式,為一個數組,可以引入多個css樣式控制組件
  • encapsulation:組件樣式封裝策略

@Component({   selector: 'app-xxx',   templateUrl: 'XXX',   styleUrls: ['XXX'],   encapsulation:ViewEncapsulation.Emulated  // 不寫則默認該值,表示該組件樣式只作用于組件本身,不影響全局樣式,在 head 中生成單獨的 style 標簽 })
登錄后復制

數據綁定

  • 數據綁定 {{data}}

  • 屬性綁定 [id]="id",其中[class.樣式類名]=“判斷表達式”是在應用單個class樣式時的常用技巧

  • 事件綁定 (keyup)="keyUpFn($event)"

  • 樣式綁定可以用 :host 這樣一個偽類選擇器,綁定的樣式作用于組件本身

  • 雙向數據綁定 [(ngModel)]

    // 注意引入:FormsModule import { FormsModule } from '@angular/forms';  <input type="text" [(ngModel)]="inputValue"/> {{inputValue}}  // 其實是一個語法糖 [ngModel]="username" (ngModelChange)="username = $event"
    登錄后復制

臟值檢測

臟值檢測:當數據改變時更新視圖(DOM)

如何進行檢測:檢測兩個狀態值(當前狀態和新狀態)

何時觸發臟值檢測:瀏覽器事件(clickmouseoverkeyup等)、setTimeout()setInterval()、HTTP請求

Angular 有兩種變更檢測策略:DefaultOnPush

可以通過在@Component元數據中設置changeDetection: ChangeDetectionStrategy.OnPush進行切換

Default

優點:每一次有異步事件發生,Angular 都會觸發變更檢測,從根組件開始遍歷其子組件,對每一個組件都進行變更檢測,對dom進行更新。

缺點:有很多組件狀態沒有發生變化,無需進行變更檢測。如果應用程序中組件越多,性能問題會越來越明顯。

OnPush

優點:組件的變更檢測完全依賴于組件的輸入(@Input),只要輸入值不變就不會觸發變更檢測,也不會對其子組件進行變更檢測,在組件很多的時候會有明顯的性能提升。

缺點:必須保證輸入(@Input)是不可變的(可以用Immutable.js解決),每一次輸入變化都必須是新的引用。

父子組件通訊

深入了解Angular(新手入門指南)

父組件給子組件傳值 @input

父組件不僅可以給子組件傳遞簡單的數據,還可把自己的方法以及整個父組件傳給子組件。

// 父組件調用子組件的時候傳入數據 <app-header [msg]="msg"></app-header>  // 子組件引入 Input 模塊 import { Component, OnInit ,Input } from '@angular/core';  // 子組件中 @Input 裝飾器接收父組件傳過來的數據 export class HeaderComponent implements OnInit {   @Input() msg:string 	constructor() { } 	ngOnInit() { } }  // 子組件中使用父組件的數據 <h2>這是頭部組件--{{msg}}</h2>
登錄后復制

**子組件觸發父組件的方法 @Output **

// 子組件引入 Output 和 EventEmitter import { Component,OnInit,Input,Output,EventEmitter} from '@angular/core';  // 子組件中實例化 EventEmitter // 用 EventEmitter 和 @Output 裝飾器配合使用 <string> 指定類型變量 @Output() private outer=new EventEmitter<string>();  // 子組件通過 EventEmitter 對象 outer 實例廣播數據 sendParent(){   this.outer.emit('msg from child') }  // 父組件調用子組件的時候,定義接收事件,outer 就是子組件的 EventEmitter 對象 outer <app-header (outer)="runParent($event)"></app-header>  // 父組件接收到數據會調用自己的 runParent, 這個時候就能拿到子組件的數據 // 接收子組件傳遞過來的數據   runParent(msg:string){    alert(msg); }
登錄后復制

父組件通過 ViewChild 主動調用子組件DOM和方法

// 給子組件定義一個名稱 <app-footer #footerChild></app-footer>  // 引入 ViewChild import { Component, OnInit ,ViewChild} from '@angular/core';  // ViewChild 和子組件關聯起來 @ViewChild('footerChild') footer;  // 調用子組件 run(){    this.footer.footerRun(); }
登錄后復制

投影組件

深入了解Angular(新手入門指南)

由于組件過度嵌套會導致數據冗余和事件傳遞,因此引入投影組件的概念

投影組件 ng-content 作為一個容器組件使用

主要用于組件動態內容的渲染,而這些內容沒有復雜的業務邏輯,也不需要重用,只是一小部分 HTML 片段

使用 ng-content 指令將父組件模板中的任意片段投影到它的子組件上

組件里面的 ng-content 部分可以被組件外部包裹的元素替代

// 表現形式: <ng-content select="樣式類/HTML標簽/指令"></ng-content>  <ng-content select="[appGridItem]"></ng-content>
登錄后復制

select 表明包含 appGridItem 的指令的元素才能投影穿透過來

Angular指令

深入了解Angular(新手入門指南)

指令可以理解為沒有模版的組件,它需要一個宿主元素(Host)

推薦使用方括號 [] 指定 Selector,使它變成一個屬性

@Directive({ selector: '[appGridItem]' })
登錄后復制

內置屬性型指令

NgClass

ngClass 是自由度和拓展性最強的樣式綁定方式

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

NgStyle

ngStyle由于是嵌入式樣式,因此可能會覆蓋掉其他樣式,需謹慎

<div [ngStyle]="{'background-color':'green'}">你好 ngStyle</div>
登錄后復制

NgModel

// 注意引入:FormsModule import { FormsModule } from '@angular/forms';  <input type="text" [(ngModel)]="inputValue"/> {{inputValue}}
登錄后復制

內置結構型指令

ngIf

ngIf 根據表達式是否成立,決定是否展示 DOM 標簽

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

ngIf else

<div *ngIf="show else ElseContent">這是 ngIF 內容</div> <ng-template #ElseContent>   <h2>這是 else 內容</h2> </ng-template>  // 結構性指令都依賴于 ng-template,*ngIf 實際上就是 ng-template 指令的 [ngIf] 屬性。
登錄后復制

ngFor

<ul>   <li *ngFor="let item of list;let i = index;">      {{item}} --{{i}}   </li> </ul>
登錄后復制

ngSwitch

<ul [ngSwitch]="score">    <li *ngSwitchCase="1">已支付</li>    <li *ngSwitchCase="2">已確認</li>    <li *ngSwitchCase="3">已發貨</li>    <li *ngSwitchDefault>已失效</li> </ul>
登錄后復制

指令事件樣式綁定

@HostBinding 綁定宿主的屬性或者樣式

@HostBinding('style.display') display = "grid";  // 用樣式綁定代替rd2的 this.setStyle('display','grid');
登錄后復制

@HostListener 綁定宿主的事件

@HostListener('click',['$event.target'])  // 第一個參數是事件名,第二個是事件攜帶參數
登錄后復制

Angular生命周期

生命周期函數通俗的講就是組件創建、組件更新、組件銷毀的時候會觸發的一系列的方法

當 Angular 使用構造函數新建一個組件或指令后,就會按下面規定的順序在特定時刻調用生命周期鉤子

  • constructor :構造函數永遠首先被調用,一般用于變量初始化以及類實例化

  • ngOnChanges :被綁定的輸入屬性變化時被調用,首次調用一定在 ngOnInit 之前。輸入屬性發生變化是觸發,但組件內部改變輸入屬性是不會觸發的。注意:如果組件沒有輸入,或者使用它時沒有提供任何輸入,那么框架就不會調用 ngOnChanges

  • ngOnInit :組件初始化時被調用,在第一輪 ngOnChanges 完成之后調用,只調用一次。使用 ngOnInit 可以在構造函數之后馬上執行復雜的初始化邏輯,同時在 Angular 設置完輸入屬性之后,可以很安全的對該組件進行構建

  • ngDoCheck :臟值檢測時調用,在變更檢測周期中 ngOnChanges 和 ngOnInit 之后

    • ngAfterContentInit :內容投影ng-content完成時調用,只在第一次 ngDoCheck 之后調用

    • ngAfterContentChecked: 每次完成被投影組件內容的變更檢測之后調用(多次)

    • ngAfterViewInit :組件視圖及子視圖初始化完成時調用,只在第一次 ngAfterContentChecked 調用一次

    • ngAfterViewChecked: 檢測組件視圖及子視圖變化之后調用(多次)

  • ngOnDestroy 當組件銷毀時調用,可以反訂閱可觀察對象和分離事件處理器,以防內存泄漏

Angular路由

路由(導航)本質上是切換視圖的一種機制,路由的導航URL并不真實存在

Angular 的路由借鑒了瀏覽器URL變化導致頁面切換的機制

Angular 是單頁程序,路由顯示的路徑不過是一種保存路由狀態的機制,這個路徑在 web 服務器上不存在

路由基本配置

/**  * 在功能模塊中定義子路由后,只要導入該模塊,等同于在根路由中直接定義  * 也就是說在 AppModule 中導入 HomeModule 的時候,  * 由于 HomeModule 中導入了 HomeRouting Module  * 在 HomeRoutingModule 中定義的路由會合并到根路由表  * 相當于直接在根模塊中定義下面的數組。  * const routes = [{  *   path: 'home',  *   component: HomeContainerComponent  * }]  */  const routes: Routes = [   {path: 'home', component: HomeComponent},   {path: 'news', component: NewsComponent},   {path: 'newscontent/:id', component: NewscontentComponent},  // 配置動態路由   {     path: '',     redirectTo: '/home',  // 重定向     pathMatch: 'full' 	},   //匹配不到路由的時候加載的組件 或者跳轉的路由   {      path: '**', /*任意的路由*/      // component:HomeComponent      redirectTo:'home'   } ]  @NgModule({   /**    * 根路由使用 `RouterModule.forRoot(routes)` 形式。    * 而功能模塊中的路由模塊使用 `outerModule.forChild(routes)` 形式。    * 啟用路由的 debug 跟蹤模式,需要在根模塊中設置 `enableTracing: true`    */   imports: [RouterModule.forRoot(routes, { enableTracing: true })],   exports: [RouterModule] }) export class AppRoutingModule { }
登錄后復制

激活路由

找到 app.component.html 根組件模板,配置 router-outlet

通過模版屬性訪問路由,即路由鏈接 routerLink

<h1>   <a [routerLink]="['/home']">首頁</a>   <a [routerLink]="['/home',tab.link]">首頁</a><!-- 路徑參數 -->   <a [routerLink]="['/home',tab.link,{name:'val1'}]">首頁</a> <!-- 路徑對象參數 -->   <a [routerLink]="['/home']" [queryParams]="{name:'val1'}">首頁</a> <!-- 查詢參數 --> </h1> <router-outlet></router-outlet>  <!-- 路由插座,占位標簽 --> <!--   路由顯示的內容是插入到 router-outlet 的同級的下方節點   而不是在 router-outlet 中包含 --> <!--   當事件處理或者達到某個條件時,可以使用手動跳轉 	this.router.navigate(['home']);  	this.router.navigate(['home',tab.link]);  	this.router.navigate(['home',tab.link,{name:'val1'}]);  	this.router.navigate(['home'],{queryParams:{name:'val1'}});  -->
登錄后復制

控制路由激活狀態的樣式 routerLinkActive

<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; }
登錄后復制

路由參數

路徑參數讀取

this.route.paramsMap.subscribe(params => {...})
登錄后復制

查詢參數讀取

this.route.queryParamsMap.subscribe(params => {...})
登錄后復制

路由傳遞一個參數及其接收方法:

傳遞參數:path:’info/:id’

接收參數:

constructor(private routerInfo: ActivatedRoute){} ngOnInit(){ 	this.routerInfo.snapshot.params['id'] }
登錄后復制

路由傳遞多個參數及其接收方法:

傳遞:[queryParams]=‘{id:1,name:‘crm’}’

接收參數:

constructor(private routerInfo: ActivatedRoute){} ngOnInit(){ 	this.routerInfo.snapshot.params['id'] 	this.routerInfo.snapshot.params['name'] }
登錄后復制

路由懶加載

懶加載子模塊,子模塊需要配置路由設置啟動子模塊 loadChildren

const routes: Routes = [     {path:'user',loadChildren:'./module/user/user.module#UserModule' },     {path:'product',loadChildren:'./module/product/product.module#ProductModule'},     {path:'article',loadChildren:'./module/article/article.module#ArticleModule'},     {path:'**',redirectTo:'user'} ];  // 上面好像會報錯 Error find module  // 配置懶加載 const routes: Routes = [     {path:'user',loadChildren:()=>import('./module/user/user.module').then(mod=>mod.UserModule)},     {path:'article',loadChildren:()=>import('./module/article/article.module').then(mod=>mod.ArticleModule)},     {path:'product',loadChildren:()=>import('./module/product/product.module').then(mod=>mod.ProductModule)},     {path:'**',redirectTo:'user'} ];
登錄后復制

Angular服務

組件不應該直接獲取或保存數據,應該聚焦于展示數據,而把數據訪問的職責委托給某個服務

獲取數據和視圖展示應該相分離,獲取數據的方法應該放在服務中

類似 VueX,全局的共享數據(通用數據)及非父子組件傳值、共享數據放在服務中

組件之間相互調用各組件里定義的方法

多個組件都用的方法(例如數據緩存的方法)放在服務(service)里

import { Injectable } from '@angular/core'; @Injectable({   providedIn: 'root', }) export class HeroService {   aa = 'abc';   constructor(){ }   ngOnInit(){ } }  import { HeroService } from '../../../services/hero/hero.service'; export class AComponent implements OnInit{   constructor(private heroService : HeroService) {} //實例化   ngOnInit(){     console.log(this.heroService.aa)   } }
登錄后復制

@Injectable()裝飾器

在 Angular 中,要把一個類定義為服務,就要用 @Injectable() 裝飾器來提供元數據,以便讓 Angular 把它作為依賴注入到組件中。

同樣,也要使用 @Injectable () 裝飾器來表明一個組件或其它類(比如另一個服務、管道或 NgModule)擁有一個依賴。

@Injectable () 裝飾器把這個服務類標記為依賴注入系統的參與者之一,它是每個 Angular 服務定義中的基本要素。

在未配置好 Angular 的依賴注入器時,Angular 實際上無法將它注入到任何位置。

@Injectable () 裝飾器具有一個名叫 providedIn 的元數據選項,providedIn 設置為 'root',即根組件中,那么該服務就可以在整個應用程序中使用了。

providedIn 提供這些值:‘root''platform''any'null

對于要用到的任何服務,必須至少注冊一個提供者。

服務可以在自己的元數據中把自己注冊為提供者,可以讓自己隨處可用,也可以為特定的模塊或組件注冊提供者。

要注冊提供者,就要在服務的 @Injectable () 裝飾器中提供它的元數據,或者在 @NgModule ()@Component () 的元數據中。

在組件中提供服務時,還可以使用 viewProdiversviewProviders 對子組件樹不可見

可以使用不同層級的提供者來配置注入器,也表示該服務的作用范圍

  • Angular 創建服務默認采用的方式:在服務本身的 @Injectable () 裝飾器中

  • 該服務只在某服務中使用:在 NgModule 的 @NgModule () 裝飾器中

  • 該服務在某組件中使用:在組件的 @Component () 裝飾器中

依賴注入

在項目中,有人提供服務,有人消耗服務,而依賴注入的機制提供了中間的接口,并替消費者創建并初始化處理

消費者只需要知道拿到的是完整可用的服務就好,至于這個服務內部的實現,甚至是它又依賴了怎樣的其他服務,都不需要關注。

Angular 通過 service共享狀態,而這些管理狀態和數據的服務便是通過依賴注入的方式進行處理的

Angular 的 service 的本質就是依賴注入,將service作為一個Injector注入到component

歸根到底,很多時候我們創建服務,是為了維護公用的狀態和數據,通過依賴注入的方式來規定哪些組件可共享

深入了解Angular(新手入門指南)

正是因為 Angular 提供的這種依賴注入機制,才能在構造函數中直接聲明實例化

  constructor(private heroService : HeroService) {} // 依賴注入
登錄后復制

深入了解Angular(新手入門指南)

先看一下 Angular 中 TS 單文件的注入

// 首先寫 @injectable 我們需要注入的東西,比如說 product @Injectable() class Product {   constructor(     private name: string,     private color: string,     private price: number,   ) { } }  class PurchaseOrder {   constructor(private product: Product){ } }   export class HomeGrandComponent implements OnInit {   constructor() { }   ngOnInit() {     // 構造一個 injector 用 create 方法 里面 providers 數組中寫我們需要構造的東西     const injector = Injector.create({       providers: [         {           provide: Product,           // 構造 Product 在 useFactory 中就會把上面定義的 product 注入到這里           useFactory: () => {             return new Product('大米手機', '黑色', 2999);           },           deps: []         },         {           provide: PurchaseOrder,           deps: [Product]         },         {           provide: token,           useValue: { baseUrl: 'http://local.dev' }         }       ]     });      console.log('injector獲取product', injector.get(PurchaseOrder).getProduct);     console.log(injector.get(token));   }
登錄后復制

再看一下Angular 中 module 模塊的注入

// .service.ts 中 @Injectable () 依賴注入 @Injectable() export class HomeService {   imageSliders: ImageSlider[] = [     {       imgUrl:'',       link: '',       caption: ''     }   ]   getBanners() {     return this.imageSliders;   } }  // 使用模塊對應的.module.ts 中 @NgModule({   declarations: [     HomeDetailComponent,   ],   providers:[HomeService], // 在 providers 直接寫對應服務,直接將服務注入模塊   imports: [SharedModule, HomeRoutingModule] })
登錄后復制

不管是在組件內還是在模塊內,我們使用 providers 的時候,就是進行了一次依賴注入的注冊和初始化

其實模塊類(NgModule)也和組件一樣,在依賴注入中是一個注入器,作為容器提供依賴注入的接口

NgModule 使我們不需要在一個組件中注入另一個組件,通過模塊類(NgModule)可以進行獲取和共享

Angular 管道

Angular 管道是編寫可以在 HTML 組件中聲明的顯示值轉換的方法

管道將數據作為輸入并將其轉換為所需的輸出

管道其實就是過濾器,用來轉換數據然后顯示給用戶

管道將整數、字符串、數組和日期作為輸入,用 | 分隔,然后根據需要轉換格式,并在瀏覽器中顯示出來

在插值表達式中,可以定義管道并根據情況使用

Angular 應用程序中可以使用許多類型的管道

內置管道

  • String -> String
    • UpperCasePipe 轉換成大寫字符
    • LowerCasePipe 轉換成小寫字符
    • TitleCasePipe 轉換成標題形式,第一個字母大寫,其余小寫
  • Number -> String
    • DecimalPipe 根據數字選項和區域設置規則格式化值
    • PercentPipe 將數字轉換為百分比字符串
    • CurrencyPipe 改變人名幣格式
  • Object -> String
    • JsonPipe 對象序列化
    • DatePipe 日期格式轉換
  • Tools
    • SlicePipe 字符串截取
    • AsyncPipe 從異步回執中解出一個值
    • I18nPluralPipe 復數化
    • I18nSelectPipe 顯示與當前值匹配的字符串

使用方法

<div>{{ 'Angular' | uppercase }}</div>  <!-- Output: ANGULAR -->  <div>{{ data | date:'yyyy-MM-dd' }}</div>  <!-- Output: 2022-05-17 -->  <div>{{ { name: 'ccc' } | json }}</div>  <!-- Output: { "name": "ccc" } -->  <!--  	管道可以接收任意數量的參數,使用方式是在管道名稱后面添加: 和參數值 	若需要傳遞多個參數則參數之間用冒號隔開  -->  <!-- 可以將多個管道連接在一起,組成管道鏈對數據進行處理 --> <div>{{ 'ccc' | slice:0:1 | uppercase }}</div>
登錄后復制

自定義管道

管道本質上就是個類,在這個類里面去實現 PipeTransfrom 接口的 transform 這個方法

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

// 引入PipeTransform是為了繼承transform方法 import { Pipe, PipeTransform } form '@angular/core';  // name屬性值慣用小駝峰寫法, name的值為html中 | 后面的名稱 @Pipe({ name: 'sexReform' })  export class SexReformPipe implements PipeTransform {     transform(value: string, args?: any): string {     // value的值為html中 | 前面傳入的值, args為名稱后傳入的參數         switch(value){             case 'male': return '男';             case 'female': return '女';             default: return '雌雄同體';         }      } }  // demo.component.ts export Class DemoComponent {     sexValue = 'female'; }  // demo.component.html <span>{{ sexValue | sexReform }}</span>  // 瀏覽器輸出 女  // 管道可以鏈式使用,還可以傳參 <span> {{date | date: 'fullDate' | uppercase}} </span> // 每一個自定義管道都需要實現 PipeTransform 接口,這個接口非常簡單,只需要實現 transform 方法即可。 // transform()方法參數格式 - transform(value: string, args1: any, args2?: any):  // value為傳入的值(即為需要用此管道處理的值, | 前面的值);  // args 為傳入的參數(?:代表可選); // html 中使用管道格式 - {{ 數據 | 管道名 : 參數1 : 參數2 }} // 與 component 一樣,pipe 需要先在 declarations 數組中聲明后使用
登錄后復制

Angular操作DOM

原生JS操作

ngAfterViewInit(){    var boxDom:any=document.getElementById('box');    boxDom.style.color='red'; }
登錄后復制

ElementRef

ElementRef 是對視圖中某個原生元素的包裝類

因為 DOM 元素不是 Angular 中的類,所以需要一個包裝類以便在 Angular 中使用和標識其類型

ElementRef 的背后是一個可渲染的具體元素。在瀏覽器中,它通常是一個 DOM 元素

class ElementRef<T> {   constructor(nativeElement: T)   nativeElement: T  //背后的原生元素,如果不支持直接訪問原生元素,則為 null(比如:在 Web Worker 環境下運行此應用的時候)。 }
登錄后復制

當需要直接訪問 DOM 時,請把本 API 作為最后選擇 。優先使用 Angular 提供的模板和數據綁定機制

如果依賴直接訪問 DOM 的方式,就可能在應用和渲染層之間產生緊耦合。這將導致無法分開兩者,也就無法將應用發布到 Web Worker 中

ViewChild

使用模板和數據綁定機制,使用 @viewChild

// 模版中給 DOM 起一個引用名字,以便可以在組件類或模版中進行引用 <div #myattr></div>  // 引入 ViewChild import { ViewChild,ElementRef } from '@angular/core';  // 用 ViewChild 綁定 DOM	 @ViewChild('myattr') myattr: ElementRef;  // 在 ngAfterViewInit 生命周期函數里可以很安全的獲取 ViewChild 引用的 DOM ngAfterViewInit(){    let attrEl = this.myattr.nativeElement; }
登錄后復制

父組件中可以通過 ViewChild 調用子組件的方法

// 給子組件定義一個名稱 <app-footer #footerChild></app-footer>  // 引入 ViewChild import { Component, OnInit ,ViewChild} from '@angular/core';  // ViewChild 和子組件關聯起來  // 如果想引用模版中的 Angular 組件,ViewChild 中可以使用引用名,也可以使用組件類型 @ViewChild('footerChild') footer;  // @ViewChild('imageSlider', { static: true }) // static指定是動態還是靜態,在*ngFor或者*ngIf中是動態,否則即為靜態,動態為 true  // 調用子組件 run(){    this.footer.footerRun(); }
登錄后復制

引用多個模版元素,可以用@ViewChildren,在ViewChildren中可以使用引用名

或者使用 Angular 組件/指令的類型,聲明類型為 QueryList<?>

<img   #img   *ngFor="let slider of sliders"   [src]="slider.imgUrl"   [alt]="slider.capiton" >  // 使用 ViewChildren 引用獲取 @ViewChildren(’img‘);  // 使用類型引用獲取 imgs: QueryList<ElementRef>;
登錄后復制

Renderer2

Renderer2 是 Angular 提供的操作 element 的抽象類,使用該類提供的方法,能夠實現在不直接接觸 DOM 的情況下操作頁面上的元素。

Renderer2 的常用方法:

  • addClass /removeClassdirective 的宿主元素添加或刪除 class

import { Directive, Renderer2, ElementRef, OnInit } from '@angular/core';  @Directive({     selector: '[testRenderer2]' })  export class TestRenderer2Directive implements OnInit {     constructor(private renderer: Renderer2, private el: ElementRef) {} // 實例化      ngOnInit() {     this.renderer.addClass(this.el.nativeElement, 'test-renderer2');     // this.renderer.removeClass(this.el.nativeElement, 'old-class');     } }
登錄后復制

  • createElement /appendChild/createText 創建 DIV 元素,插入文本內容,并將其掛載到宿主元素上

import { Directive, Renderer2, ElementRef, OnInit } from '@angular/core';  constructor(private renderer: Renderer2, private el: ElementRef) {}  ngOnInit() {     const div = this.renderer.createElement('div');     const text = this.renderer.createText('Hello world!');          this.renderer.appendChild(div, text);     this.renderer.appendChild(this.el.nativeElement, div); }
登錄后復制

  • setAttribute /removeAttribute 在宿主元素上添加或刪除 attribute

import { Directive, Renderer2, ElementRef, OnInit } from '@angular/core';  constructor(private renderer: Renderer2, private el: ElementRef) {}  ngOnInit() {     this.renderer.setAttribute(this.el.nativeElement, 'aria-hidden', 'true'); }
登錄后復制

  • setStyle /removeStyle 在宿主元素上添加 inline-style

import { Directive, Renderer2, ElementRef, OnInit } from '@angular/core';  constructor(private renderer: Renderer2, private el: ElementRef) {}  ngOnInit() {     this.renderer.setStyle(         this.el.nativeElement,         'border-left',         '2px dashed olive'     ); }
登錄后復制

移除 inline-style :

constructor(private renderer: Renderer2, private el: ElementRef) {}  ngOnInit() {     this.renderer.removeStyle(this.el.nativeElement, 'border-left'); }
登錄后復制

  • setProperty 設置宿主元素的 property 的值

constructor(private renderer: Renderer2, private el: ElementRef) {}  ngOnInit() {     this.renderer.setProperty(this.el.nativeElement, 'alt', 'Cute alligator'); }
登錄后復制

直接操作DOM,Angular不推薦。盡量采用 @viewChildrenderer2 組合,Angular推薦使用 constructor(private rd2: Renderer2) {} 依賴注入,

import {   Component,   OnInit,   Renderer2,   ViewChild, } from '@angular/core'; import { AboxItemComponent } from './abox-item/abox-item.component';   @Component({   selector: 'app-abox',   templateUrl: './abox.component.html',   styleUrls: ['./abox.component.less'], }) export class AboxComponent implements OnInit {   private container;   activeIndex: number;   @ViewChild('containers') containers: any;   constructor(private rd2: Renderer2) {}     ngOnInit(): void {}     ngAfterViewInit(): void {     this.container = this.containers.nativeElement;     this.initCarouselWidth();   }        initCarouselWidth() {     this.rd2.setStyle(this.container, 'width', '100px');   } }
登錄后復制

Angular網絡請求

HttpClient

需導入 HttpClientModule ,只在根模塊中導入,并且整個應用只需導入一次,不用在其他模塊導入

在構造函數中注入HttpClientget/post方法對應HTTP方法,這些方法是泛型的,可以直接把返回的JSON轉換成對應類型。若是不規范的請求,使用request方法

返回的值是 Observable,必須訂閱才會發送請求,否則不會發送

get 請求數據

// 在 app.module.ts 中引入 HttpClientModule 并注入 import {HttpClientModule} from '@angular/common/http'; imports: [   BrowserModule,   HttpClientModule ]  // 在用到的地方引入 HttpClient 并在構造函數聲明 import {HttpClient} from "@angular/common/http"; constructor(private http: HttpClient,private cd: ChangeDetectorRef) { } // 依賴注入  // get 請求數據 var api = "http://baidu.com/api/productlist"; this.http.get(api).subscribe(response => {   console.log(response);   this.cd.markForCheck();   // 如果改變了臟值檢測的變更原則 changeDetection: ChangeDetectionStrategy.OnPush   // 則需要使用 this.cd.markForCheck() 手動提醒 Angular 這里需要進行臟值檢測 });
登錄后復制

post 提交數據

// 在 app.module.ts 中引入 HttpClientModule 并注入 import {HttpClientModule} from '@angular/common/http'; imports: [    BrowserModule,    HttpClientModule ]  // 在用到的地方引入 HttpClient 、HttpHeaders 并在構造函數聲明 HttpClient import {HttpClient,HttpHeaders} from "@angular/common/http"; constructor(private http:HttpClient) { } // 實例化  // post 提交數據 const httpOptions = {     headers: new HttpHeaders({ 'Content-Type': 'application/json' }) }; var api = "http://127.0.0.1:4200/doLogin"; this.http.post(api,{username:'瑞萌萌',age:'22'},httpOptions).subscribe(response => { 		console.log(response); });
登錄后復制

Jsonp請求數據

// 在 app.module.ts 中引入 HttpClientModule、HttpClientJsonpModule 并注入 import {HttpClientModule,HttpClientJsonpModule} from'@angular/common/http'; imports: [    BrowserModule,    HttpClientModule,    HttpClientJsonpModule ]  // 在用到的地方引入 HttpClient 并在構造函數聲明 import {HttpClient} from "@angular/common/http"; constructor(private http:HttpClient) { } // 實例化  // jsonp 請求數據 var api = "http://baidu.com/api/productlist"; this.http.jsonp(api,'callback').subscribe(response => {    console.log(response); });
登錄后復制

攔截器

Angular 攔截器是 Angular 應用中全局捕獲和修改 HTTP 請求和響應的方式,例如攜帶 Token 和捕獲 Error

前提是只能攔截使用 HttpClientModule 發出的請求,如果使用 axios 則攔截不到

創建攔截器

// 使用命令 ng g interceptor name,在這里創建攔截器 ng g interceptor LanJieQi // cli 生成攔截器是沒有簡寫方式的  import { Injectable } from '@angular/core'; import {   HttpRequest,   HttpHandler,   HttpEvent,   HttpInterceptor } from '@angular/common/http'; import { Observable } from 'rxjs';  @Injectable() export class LanJieQiInterceptor implements HttpInterceptor {   constructor() {}   // 默認的 intercept() 方法只是單純的將請求轉發給下一個攔截器(如果有),并最終返回 HTTP 響應體的 Observable   // request: HttpRequest<unknown> 表示請求對象,包含了請求相關的所有信息,unknown指定請求體body的類型   // next: HttpHandler 請求對象修改完成,將修改后的請求對象通過next中的handle方法傳回真正發送請求的方法中   intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> 	{     // next 對象表示攔截器鏈表中的下一個攔截器(在應用中可以設置多個攔截器)     return next.handle(request);   } }
登錄后復制

注入攔截器

// 在 @NgModule 模塊中注入攔截器 // 攔截器也是一個由 Angular 依賴注入 (DI) 系統管理的服務,也必須先提供這個攔截器類,才能使用它 // 由于攔截器是 HttpClient 服務的依賴,所以必須在提供 HttpClient 的同一個(或其各級父注入器)注入器中提供這些攔截器 @NgModule({   imports: [     HttpClientModule     // others...   ],   providers: [     {       provide: HTTP_INTERCEPTORS,       useClass: LanJieQiInterceptor,       // multi: true 表明 HTTP_INTERCEPTORS 是一個多重提供者的令牌,表示這個令牌可以注入多個攔截器       multi: true     },   ],   bootstrap: [AppComponent] })  export class AppModule { }
登錄后復制

請求頭攔截

@Injectable()export class LanJieQiInterceptor implements HttpInterceptor {   constructor() {}   intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> 	{     // 為了統一設置請求頭,需要修改請求     // 但 HttpRequest 和 HttpResponse 實例的屬性卻是只讀(readonly)的     // 所以修改前需要先 clone 一份,修改這個克隆體后再把它傳給 next.handle()     let req = request.clone({     	setHeaders:{       	token:"123456" // 在請求頭中增加 token:123456     	} 			// setHeaders 和 headers: request.headers.set('token', '123456') 一致   	})   	return next.handle(req)// 將修改后的請求返回給應用   }}
登錄后復制

響應捕獲

@Injectable() export class LanJieQiInterceptor implements HttpInterceptor {   constructor() {}   intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> 	{     // 為了統一設置請求頭,需要修改請求     // 但 HttpRequest 和 HttpResponse 實例的屬性卻是只讀(readonly)的     // 所以修改前需要先 clone 一份,修改這個克隆體后再把它傳給 next.handle()     let req = request.clone({     	setHeaders:{       	token:"123456" // 在請求頭中增加 token:123456     	} 			// setHeaders 和 headers: request.headers.set('token', '123456') 一致   	})   	return next.handle(req)// 將修改后的請求返回給應用   } }
登錄后復制

如果有多個攔截器,請求順序是按照配置順序執行,響應攔截則是相反的順序

如果提供攔截器的順序是先 A再 B再 C,那么請求階段的執行順序就是 A->B->C,而響應階段的執行順序則是 C->B->A

Angular表單

模版驅動表單

模板驅動表單在往應用中添加簡單的表單時非常有用,但是不像響應式表單那么容易擴展

如果有非常基本的表單需求和簡單到能用模板管理的邏輯,就使用模板驅動表單

響應式表單和模板驅動表單共享了一些底層構造塊:

FormControl 實例用于追蹤單個表單控件的值和驗證狀態

FormGroup 用于追蹤一個表單控件組的值和狀態

FormArray 用于追蹤表單控件數組的值和狀態,有長度屬性,通常用來代表一個可以增長的字段集合

ControlValueAccessor 用于在 Angular 的 FormControl 實例和原生 DOM 元素之間創建一個橋梁

FormControlFormGroup 是 angular 中兩個最基本的表單對象

FormControl 代表單一的輸入字段,它是 Angular 表單中最小單員,它封裝了這些字段的值和狀態,比如是否有效、是否臟(被修改過)或是否有錯誤等

FormGroup 可以為一組 FormControl 提供總包接口(wrapper interface),來管理多個 FormControl

當我們試圖從 FormGroup 中獲取 value 時,會收到一個 “鍵值對” 結構的對象

它能讓我們從表單中一次性獲取全部的值而無需逐一遍歷 FormControl,使用起來相當順手

FormGroupFormControl 都繼承自同一個祖先 AbstractControltractControl(這是 FormControlFormGroupFormArray 的基類)

首先加載 FormsModule

// 先在 NgModule 中導入了 FormsModule 表單庫 // FormsModule 為我們提供了一些模板驅動的指令,例如:ngModel、NgForm import {    FormsModule } from '@angular/forms';   @NgModule({    declarations: [      FormsDemoApp,      DemoFormSku,      // ... our declarations here    ],    imports: [      BrowserModule,      FormsModule,   ],    bootstrap: [ FormsDemoApp ]  })  class FormsDemoAppModule {}
登錄后復制

接下來創建一個模版表單

 <div>       <h2>基礎表單:商品名稱</h2>       <form #f="ngForm" (ngSubmit)="onSubmit(f.value)">         <div class="sku">           <label for="skuInput">商品名稱:</label>           <input             type="text"             id="skuInput"             placeholder="商品名稱"             name="sku" //使用form時必須定義,可以理解為當前控件的名字             ngModel           />         </div>         <button>提交</button>       </form>     </div>
登錄后復制

我們導入了 FormsModule,因此可以在視圖中使用 NgForm

當這些指令在視圖中可用時,它就會被附加到任何能匹配其 selector 的節點上

NgForm 做了一件便利但隱晦的工作:它的選擇器包含 form 標簽(而不用顯式添加 ngForm 屬性)

這意味著當導入 FormsModule 時候,NgForm 就會被自動附加到視圖中所有的標簽上

NgForm 提供了兩個重要的功能:

  • 一個 ngFormFormGroup 對象
  • 一個輸出事件 (ngSubmit)

 <form #f="ngForm" (ngSubmit)="onSubmit(f.value)" >  <!--  	這里使用了 #f=“ngForm”,#v=thing 的意思是我們希望在當前視圖中創建一個局部變量 	這里為視圖中的 ngForm 創建了一個別名,并綁定到變量 #f 	這個 ngForm 是由 NgForm 指令導出的 	ngForm 的類型的對象是 FormGroup 類型的 	這意味著可以在視圖中把變量 f 當作 FormGroup 使用,而這也正是我們在輸出事件 (ngSubmit) 中的使用方法 	在表單中綁定 ngSubmit 事件 (ngSubmit)=“onSubmit (f.value)“ 	(ngSubmit) 來自 NgForm 指令 	onSubmit() 將會在組件類中進行定義 	f 就是 FormGroup ,而 .value 會以鍵值對的形式返回 FormGroup 中所有控件的值 	 	總結:當提交表單時,將會以該表單的值作為參數,調用組件實例上的 `onSubmit` 方法 -->
登錄后復制

NgModel 會創建一個新的 FormControl 對象,把它自動添加到父 FormGroup 上(這里也就是 form 表單對象)

并把這個 FormControl 對象綁定到一個 DOM 上

也就是說,它會在視圖中的 input 標簽和 FormControl 對象之間建立關聯

這種關聯是通過 name 屬性建立的,在本例中是 "name"

響應式表單

使用 ngForm 構建 FormControlFormGroup 很方便,但是無法提供定制化選項,因此引入響應式表單

響應式表單提供了一種模型驅動的方式來處理表單輸入,其中的值會隨時間而變化

使用響應式表單時,通過編寫 TypeScript 代碼而不是 HTML 代碼來創建一個底層的數據模型

在這個模型定義好以后,使用一些特定的指令將模板上的 HTML 元素與底層的數據模型連接在一起

FormBuilder 是一個名副其實的表單構建助手(可以把他看作一個 “工廠” 對象)

在先前的例子中添加一個 FormBuilder,然后在組件定義類中使用 FormGroup

// 先在 NgModule 中導入了 ReactiveFormsModule 表單庫 import {    ReactiveFormsModule  } from '@angular/forms';  @NgModule({   imports: [     FormsModule,     ReactiveFormsModule   ] })   // 使用 formGroup 和 formControl 指令來構建這個組件,需要導入相應的類 import {    FormBuilder,    FormGroup,   ReactiveFormsModule } from '@angular/forms';   // 在組件類上注入一個從 FormBuilder 類創建的對象實例,并把它賦值給 fb 變量(來自構造函數) export class DemoFormSkuBuilder {    myForm: FormGroup;  // myForm 是 FormGroup 類型   constructor(fb: FormBuilder) {      // FormBuilder 中的 group 方法用于創建一個新的 FormGroup     // group 方法的參數是代表組內各個 FormControl 的鍵值對     this.myForm = fb.group({  // 調用 fb.group () 來創建 FormGroup       // 設置一個名為 sku 的控件,控件的默認值為 "123456"       'sku': ['123456']      });    }   onSubmit(value: string): void {      console.log('submit value:', value);    }  }
登錄后復制

在視圖表單中使用自定義的 FormGroup

<h2 class="ui header">Demo Form: Sku with Builder</h2> <!--   	當導入 FormsModule 時,ngForm 就會自動創建它自己的 FormGroup 	但這里不希望使用外部的 FormGroup,而是使用 FormBuilder 創建這個 myForm 實例變量 	Angular提供了 formGroup 指令,能讓我們使用現有的 FormGroup 	NgForm 不會應用到帶 formGroup 屬性的節點上 	這里我們告訴Angular,想用 myForm 作為這個表單的 FormGroup --> <form [formGroup]="myForm"    <label for="skuInput"> SKU </label>    <input type="text"       id="skuInput"       placeholder="SKU"       [formControl]="myForm.controls['sku']"> <!--   	將 FormControl 綁定到 input 標簽上 :  	ngModel 會創建一個新的 FormControl 對象并附加到父 FormGroup 中 	但在例子中,我們已經用 FormBuilder 創建了自己的 FormControl 	要將現有的 FormControl 綁定到 input 上,可以用 formControl 指令 	將 input 標簽上的 formControl 指令指向 myForm.controls 上現有的 FormControl 控件 sku   -->
登錄后復制

記住以下兩點:

  1. 如果想隱式創建新的 FormGroup 和 FormControl,使用:ngForm、ngModel
  2. 如果要綁定一個現有的 FormGroup 和 FormControl,使用:formGroup、formControl

表單驗證

用戶輸入的數據格式并不總是正確的,如果有人輸入錯誤的數據格式,我們希望給他反饋并阻止他提交表單

因此,我們要用到驗證器,由 validators 模塊提供

Validators.required 是最簡單的驗證,表明指定的字段是必填項,否則就認為 FormControl 是無效的

如果 FormGroup 中有一個 FormControl 是無效的, 那整個 FormGroup 都是無效的

要為 FormControl 對象分配一個驗證器 ,可以直接把它作為第二個參數傳給 FormControl 的構造函數

const control = new FormControl('name', Validators.required);  // 在組件定義類中使用 FormBuilder   constructor(fb: FormBuilder) {      this.myForm = fb.group({        'name': ['',Validators.required]      });      this.name = this.myForm.controls['name'];    }
登錄后復制

在視圖中檢查驗證器的狀態,并據此采取行動

template:`<div>       <h2>商品表單:商品名稱</h2>       <form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">         <div>           <label for="nameInput">商品名稱:</label>           <input             type="text"             id="nameInput"             placeholder="請輸入名稱"             [formControl]="myForm.controls['name']"           />           <div style="color:red" *ngIf="!name.valid">             名稱無效           </div>           <div style="color:red" *ngIf="name.hasError('textinvalid')">             名稱不是以“123”開頭           </div>           <div *ngIf="name.dirty">             數據已變動           </div>         </div>         <div>           <label for="codeInput">商品料號:</label>           <input             type="text"             id="codeInput"             placeholder="請輸入料號"             [formControl]="myForm.controls['code']"           />           <div             style="color:red"             *ngIf="myForm.controls.code.hasError('required')"           >             該項必填           </div>           <div             style="color:red"             *ngIf="myForm.controls.code.hasError('pattern')"           >             只可輸入數字和英文           </div>         </div>         <div style="color:green" *ngIf="myForm.isvalid">           表單無效         </div>         <div style="color:green" *ngIf="myForm.valid">           表單有效         </div>         <button type="submit">提交</button>       </form>     </div>` export class NonInWarehouseComponent implements OnInit {   myForm: FormGroup;   name: AbstractControl;   constructor(fb: FormBuilder) {     this.myForm = fb.group({       name: ['牛奶', Validators.compose([Validators.required, textValidator])],       code: ['', [Validators.required, Validators.pattern('^[A-Za-z0-9]*$')]],     });     this.name = this.myForm.controls.name;   }   ngOnInit() {     const nameControl = new FormControl('nate');     console.log('nameControl', nameControl);   }   onSubmit(a: any) {     console.log('a', a);   } }
登錄后復制

內置校驗器

Angular 提供了幾個內置校驗器,下面是比較常用的校驗器:

  • Validators.required – 表單控件值非空
  • Validators.email – 表單控件值的格式是 email
  • Validators.minLength() – 表單控件值的最小長度
  • Validators.maxLength() – 表單控件值的最大長度
  • Validators.pattern() – 表單控件的值需匹配 pattern 對應的模式(正則表達式)

自定義驗證器

假設我們的 name 有特殊的驗證需求,比如 name 必須以 123 作為開始

當輸入值(控件的值 control.value)不是以 123 作為開始時,驗證器會返回錯誤代碼 invalidSku

// angular 源代碼中實現 Validators.required  export class Validators {   // 接收一個 AbstractControl 對象作為輸入 	static required(control: AbstractControl): ValidationErrors | null; } // 當驗證器失敗時,會返回一個 String Map<string,any> 對象,他的鍵是” 錯誤代碼 “,它的值是 true export declare type ValidationErrors = {     [key: string]: any; };  // 自定義驗證器 function textValidator(   controls: FormControl // 因為FormControl繼承于 AbstractControl 所以也可以寫成FormControl對象 ): {   [s: string]: boolean; } {   if (!controls.value.match(/^123/)) {     return { textinvalid: true };   } }
登錄后復制

FormControl 分配驗證器,但是 name 已經有一個驗證器了,如何在同一個字段上添加多個驗證器

Validators.compose 來實現

Validators.compose 把兩個驗證器包裝在一起,我們可以將其賦值給 FormControl

只有當兩個驗證器都合法時,FormControl 才是合法的

Validators.compose([Validators.required, textValidator]) // 不用compose   [Validators.required, textValidator] // 保留 compose 是為了向以前歷史版本進行兼容,不用 compose 也可實現
登錄后復制

動態表單

要實現 Angular 動態表單,主要使用 formArray 方法,formArray 生成的實例是一個數組,在這個數組中可以動態的放入 formGroupformControl,這樣便形成了動態表單。

export class ReativeFormsComponent implements OnInit {   ngOnInit() {     this.addContact()   }   //動態表單   personMess: FormGroup = new FormGroup({     //生成動態表單數組     contacts: new FormArray([])    })   //獲取數組對象   get contacts(){     return this.personMess.get('contacts') as FormArray   }   //增加一個表單組   addContact(){     let myContact = new FormGroup({       name: new FormControl(),       phone: new FormControl()     })     this.contacts.push(myContact)   }    //刪除一個表單組   deleteContact(i:number){     this.contacts.removeAt(i)   }   //提交表單   OnSubmit() {     console.log(this.personMess.value)   } }
登錄后復制

<form [formGroup]="personMess" (submit)="OnSubmit()">   <div formArrayName="contacts">     <!-- 注意:這里遍歷的時contacts.controls -->     <div *ngFor="let contact of contacts.controls;let i =index" [formGroupName]="i">       <input type="text" formControlName="name">       <input type="text" formControlName="phone">       <button (click)="deleteContact(i)">刪除信息</button>     </div>   </div>   <button (click)="addContact()">添加信息</button><br>   <input type="submit"> </form>
登錄后復制

Angular CDK

CDK 是 Component Dev kit 的簡稱,是 Angular Material 團隊在開發 Library 時發現組件有很多相似的地方,最后進行了抽取,提煉出了公共的邏輯,這部分即是 CDK

官方用了一個很形象的比喻:如果組件庫是火箭飛船,那么 CDK 就是發動機零件盒
深入了解Angular(新手入門指南)

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
主站蜘蛛池模板: 欧美在线视频一区二区三区 | 性视频在线播放 | 免费国产在线观看 | 一级片黄片毛片 | 天天操,夜夜操 | 丁香午夜 | 天堂在线网 | 欧美日韩在线第一页 | 国产一区二区三区免费 | 欧美综合激情 | 成人在线中文字幕 | 美女av网站 | 亚洲午夜精品一区二区三区他趣 | 人人看人人草 | 一级大片免费 | 亚洲午夜激情网 | 亚洲综合视频在线 | 中文字幕亚洲高清 | 国产激情网 | 婷婷久久久久久 | 四虎永久在线观看 | 黄色一级视屏 | 中文字幕在线观看第二页 | 浪浪视频在线观看 | 97九色| 欧美a在线| 国产高清视频在线 | 欧美黑人性xxx猛交 欧美色欧美色 | 淫片一级国产 | 欧美精品一区二区三区视频 | 亚洲区综合 | 欧美区国产区 | 夜久久久 | 打开每日更新在线观看 | 免费看毛片的网站 | 亚洲综合a | 久久久成人精品视频 | 久草毛片 | 男女精品视频 | 五月天激情国产综合婷婷婷 | 婷婷操| 欧美调教视频 | 成人毛片基地 | 91高潮胡言乱语对白刺激国产 | 夜夜狠狠 | 亚洲精品理论 | 免费不卡毛片 | 久久亚洲精品石原莉奈 | 色哟哟在线免费观看 | 亚洲国产成人91精品 | 色av网站 | 欧美激情网站 | 中年夫妇大白天啪啪高潮不断 | 九九热在线视频播放 | 国内自拍视频在线播放 | av综合资源 | 香蕉av777xxx色综合一区 | chinese真实伦对白露脸 | 青青草55| 99色综合 | av免费网址在线观看 | 草草影院最新地址 | 日韩欧美亚洲精品 | 在线看av的网址 | 香蕉av网 | 亚洲国产精品一区二区第一页 | 1024手机在线观看 | 欧美综合成人 | 精品久久免费看 | 日本性久久| 91亚洲视频 | 亚洲欧美精品午睡沙发 | 91一区二区在线观看 | 日韩中文字幕在线观看 | 成人国产三级 | 国产资源在线播放 | 日韩欧美综合在线 | 91爱爱网 | 亚洲综合视频图片 | 国产精品a成v人在线播放 | 一区二区三区手机在线观看 | 天天操天天干天天摸 | 在线看日韩 | 一本一道久久a久久精品综合蜜臀 | 91网站在线观看视频 | 国产又粗又猛又黄又爽无遮挡 | 亚洲三级理论 | 天天操 夜夜操 | 国产亚洲欧美日韩高清 | 激情久久网 | 久草福利资源在线观看 | 91麻豆免费视频 | 91在线观看.| 国产高清亚洲 | 亚洲一区二区欧美 | 九九热在线视频播放 | 黄色av网站免费观看 | 影音先锋亚洲精品 | 极品美女销魂一区二区三区 | 久久你懂的 | 国产高清免费av | 亚洲一区免费在线观看 | 国产每日更新 | 日本免费久久 | 久久精品国产精品亚洲毛片 | 91岛国 | 黄色国产大片 | 亚洲va欧美va人人爽 | 久久这里有精品 | 成人亚洲视频 | 黄色三级网络 | 日韩精品一区在线 | 欧美天天爽 | 五月综合激情日本mⅴ | 懂色一区二区三区免费观看 | 午夜精品久久久久久久第一页按摩 | 91青青操| 国产第八页 | www视频在线观看网站 | 欧美性猛交xxxx乱大交hd | 国产丝袜自拍 | 中日韩乱码一二新区 | 中文字幕一区二区视频 | 97在线精品 | 悠悠av| 自拍偷拍在线视频 | 欧美成人视屏 | 久久久久久久久久国产精品 | 欧美性插视频 | av在线观| 久久99久久精品久久久久久 | 国产精品看片 | 欧美一级淫片免费视频黄 | 青青草精品在线视频 | 红桃视频黄色 | 免费看黄色网址 | 久久咪咪| 久久女| 久久午夜精品 | 一区在线观看 | 五月婷婷六月丁香综合 | 亚洲精品国产第一综合99久久 | 天堂网在线播放 | 久久久久久综合 | 在线日韩亚洲 | 欧美一级片| 理论av| 亚洲国产精品自拍视频 | 亚洲最大视频网 | 亚洲成人一区在线 | 日韩精品视频在线播放 | 欧美五月激情 | 成人免费一级伦理片在线播放 | 亚洲草片 | 午夜视频1000 | 图片区视频区小说区 | 天堂中文字幕在线观看 | 毛片网站免费观看 | www.久久艹 | 精品国产一区二区三区av 性色 | 亚洲人人干| 成a人片亚洲日本久久 | 亚洲一区二区三区综合 | 在线播放视频一区 | 亚洲好视频 | 91亚洲精 | 欧美日韩少妇精品 | 亚洲激情啪啪 | 成人综合区 | 毛片网站在线看 | 久久精品在线播放 | 亚洲一二区视频 | 91精品国产福利在线观看 | 91成人一区 | 亚洲天堂中文字幕在线 | 国产91视频在线 | 91在线视频免费播放 | av黄色免费 | 男人和女人日b视频 | 国产精品久久久久久久久久久久久久 | 免费精品视频一区二区三区 | 亚洲欧美综合在线观看 | 欧洲一级视频 | 夜夜操操操操 | 极品久久久| 一区二区三区视频免费看 | 一级特黄aaa | 午夜精品福利在线观看 | 五月在线视频 | 国产三级在线免费 | 国产成人精品福利 | 免费吸乳羞羞网站视频 | 四色成人av永久网址 | 成人免费视频视频 | 久久天天躁狠狠躁夜夜97 | 国产黄色在线播放 | 一级黄色录相 | 亚洲福利视频网站 | 饥渴少妇勾引水电工av | 日皮毛片 | 国产精品美女一区二区 | 国产又黄又| 最新中文字幕在线观看 | 亚洲精品久久久9婷婷中文字幕 | 黄色的视频网站 | 亚洲综合在线视频 | 四虎影视黄色 | 国产视频一区在线播放 | 国产精品久久久久久久久久久不卡 | 最近的2019中文字幕免费一页 | 国产精品自拍网站 | 欧美日本中文字幕 | 蜜桃视频污在线观看 | 黄色动漫免费在线观看 | 国产又粗又长又黄视频 | 1024毛片| av在线免费网站 | 日韩综合一区二区 | 丁香婷婷久久 | 岛国av一区| 亚洲欧美日韩偷拍 | 视频一区亚洲 | 欧洲做受高潮欧美裸体艺术 | 国产伦精品一区二区三区照片 | 日本少妇激情视频 | 国产一区二区三区视频在线观看 | 亚洲天堂成人av | 九色精品 | 日韩欧美高清在线观看 | 1024久久 | 亚洲日本天堂 | 日本成人片在线 | 国产伦精品一区二区三区高清版禁 | 亚洲免费视 | 91丝袜在线观看 | 91视频在线观看视频 | 91在线视频导航 | 免费毛片视频网站 | 三级国产三级在线 | 国产在线视频一区二区三区 | 国产精品久久久久久久久免费看 | 男人视频网 | 嫩草亚洲| 一级性黄色片 | 成人免费大片黄在线播放 | 精品一区在线视频 | 天天拍夜夜操 | 欧美在线 | 亚洲 | 三级麻豆| 在线免费激情视频 | 久久久国产精品视频 | 国产99精品视频 | 91精品国产91久久久 | 综合精品视频 | 精品久久久久香蕉网 | 3d动漫啪啪精品一区二区中文字幕 | 久久久久久久久久久影视 | 手机在线亚洲 | 久久夜色网 | 性毛片 | 日本熟伦人妇xxxx | 亚洲人成免费 | av黄在线观看| 国产三级在线观看视频 | 美女日批网站 | 亚洲v国产v欧美v久久久久久 | 男人天堂一区 | 成人综合精品 | 亚洲视频一二区 | 欧美福利影院 | 国产精品精 | 欧美巨大荫蒂茸毛毛人妖 | 91在线视频一区 | 亚洲成av人片在线观看 | 国产乱淫av免费 | 中文字幕在线观看日本 | 久久精品色 | 丰满女邻居的色诱4hd | 波多野结衣一级 | 国产伦精品一区二区免费 | 奇米影视网| 欧美日韩国产在线 | 激情网综合 | 日韩在线视频一区二区三区 | 久色91| 久青草视频在线观看 | 国户精品久久久久久久久久久不卡 | 国内精品视频在线 | 欧美日韩国产综合在线 | 久久久国产成人 | 人人艹视频 | 久久99国产精品视频 | 欧日韩一区二区三区 | 佐佐木明希99精品久久 | 免费萌白酱国产一区二区三区 | 特级黄色一级片 | 天堂а√在线最新版中文在线 | 亚洲香蕉在线观看 | 亚洲久草 | 香蕉视频在线观看黄 | 五十路中文字幕 | 看免费黄色片 | 亚洲综合欧美日韩 | 日韩狠狠操 | 加勒比日韩 | 欧美伦理在线观看 | 国产精品3区 | 九九久久精品视频 | 精品国产一二三 | 男女拍拍拍 | 999xxxx| 久久久久99精品国产片 | 久久午夜鲁丝片 | 久久免费看视频 | h网站在线| 天天干在线播放 | 97超碰网| 伊伊总综合网 | 亚洲国产综合精品久久久久久 | 国产在线一二区 | 双性皇帝高h喷汁呻吟 | 4438色| 免费一级特黄特色大片 | 色婷网 | 久久视频免费 | 中日黄色片 | 欧美视频在线观看一区二区 | 午夜精品久久久久久久99 | 香蕉伊人 | 中文字幕在线视频观看 | 永久黄网站色视频免费 | 在线观看国产亚洲 | 精品久久久久久亚洲综合网站 | 日韩欧美在线中文字幕 | 91av在线播放视频 | 黄色三级片毛片 | 久久2019| 精品视频一区二区在线观看 | 国产精品亚洲а∨天堂免在线 | 真人真事免费毛片 | 欧美日韩视频在线观看一区 | 亚洲春色网 | 亚洲a一片| 久久aaa| 户外少妇对白啪啪野战 | 国产最爽的乱淫视频国语对白 | 日本综合久久 | 色秀视频在线观看 | 国产精品婷婷久久爽一下 | 欧美整片在线观看 | 九九久久国产精品 | 欧美午夜精品一区二区蜜桃 | 日本做受 | 伊人久久久久久久久久久久久 | 二区在线观看 | 久久久久亚洲天堂 | 8mav精品成人| 3d一区二区 | 国产福利免费视频 | 综合激情五月婷婷 | 国产精品久久久久久久久久免费 | 国产精品视频一区二区二 | 久草香蕉在线视频 | 久久夜色网 | 一区二区三区av在线 | av毛片网 | 狼色网| 久久久sm调教网站 | 热热热色 | 在线只有精品 | 国产精品第10页 | 91黄版| 日韩精品中文字幕一区二区三区 | 国产伦精品一区二区三区免费优势 | 爆操老女人 | 一本加勒比hezyo综合 | 欧美色视频在线 | 欧美精品久久久久久久久久 | 亚洲国产精品999久久久婷婷 | 一级性爱视频 | 美日韩免费视频 | 亚洲欧美一区二区三区在线观看 | 污污视频在线看 | 国产999视频| 亚洲第一国产视频 | 天天干在线观看 | 成人吃奶视频 | 国产aaa大片| 韩国毛片一区二区三区 | 久久精品10 | 这里只有精品视频在线播放 | 欧美偷拍一区二区三区 | 乱亲女h秽乱长久久久 | 欧美在线视频一区 | 天天操天天射天天爽 | 蜜桃av一区 | 色婷婷综合久久久中文字幕 | 亚洲天堂影音先锋 | 国产福利一区二区三区视频 | 成人av动漫| 中文字幕日韩高清 | 免费看操片| 九九热免费视频 | 又色又爽又黄18网站 | 污污视频免费网站 | 天堂8中文 | 色呦呦中文字幕 | 久久99精品久久久久久秒播放器 | 成年视频在线 | 日韩91视频| 成人性生生活性生交3 | 久久狠狠爱 | 成人黄色大片 | 黄色a视频 | 成人免费在线视频 | 欧美三级精品 | 美女黄色免费网站 | 国产91对白在线播放 | 在线观看污污视频 | 国产精品av一区 | 九九色影院 | 欧美va亚洲va | 国产精品嫩草影院精东 | 日韩精品视频在线免费观看 | 日本国产一区二区 | 欧美午夜精品一区二区 | 99re免费视频| 欧美日韩综合在线 | yjizz国产| 欧美啪啪一区 | 婷婷久久五月天 | 久久福利小视频 | 色五夜| www.色涩 | 国产麻豆精品久久一二三 | 嫩草视频在线免费观看 | 久久久久久久久网站 | a一级黄色片 | 国语自产少妇精品视频 | 亚洲午夜久久久久久久国产 | 日本一级淫片免费放 | 欧美黄色片视频 | 中文字幕一二 | 特黄一级片 | 激情网站视频 | 日韩在线观看第一页 | 日韩美女啪啪 | 新天堂在线 | 一区二区不卡 | 极品少妇一区 | 午夜精品在线 | 亚洲国产三级 | 欧美色偷偷 | 老外毛片 | 亚洲综合福利 | www.av72| 久久久久蜜桃 | 黄色小视频网 | 操极品| 国产污视频在线 | 蜜桃久久一区二区三区 | 国产一区在线免费观看 | 中文字幕精品一区二区精品 | 亚洲欧洲精品成人久久曰影片 | 三级视频在线看 | 91禁外国网站 | 黄色污在线观看 | 性开放网站 | 国产欧美视频在线观看 | 999久久久久久| 日日爱网站 | 观看av在线| 天堂中文在线官网 | 污在线观看| 岛国精品在线 | 91超薄丝袜肉丝一区二区 | 91网在线观看 | 91丨九色丨国产在线 | 综合视频在线观看 | 自拍偷拍欧美视频 | www一区二区| 精品美女www爽爽爽视频 | 香蕉国产精品视频 | 欧美v日韩| αv在线| 幸福宝在线观看 | 狠狠爱亚洲| 91天堂在线视频 | 蕾丝视频污 | 999久久久久久久久6666 | 天堂中文av| 久色视频在线 | 欧美做受xxxxxⅹ性视频 | 日日操操 | 亚洲免费观看高清在线观看 | www.久久久久久久久 | 潘金莲一级淫片a.aaaaa播放 | 日韩欧美视频在线播放 | 亚洲第一伊人 | 1024久久| 国产成人免费观看视频 | 免费在线看黄网站 | 日本人xxxⅹ18hd19hd | 久久一区二区三区视频 | 亚州综合 | 欧美日韩一二三四区 | 操操网址 | 偷拍一区二区 | 五月天激情综合 | 91网入口| 亚洲精品乱码久久久久久9色 | av在线免费播放不卡 | 欧美精品乱码久久久久久按摩 | 国产成人区| 国产精品成人免费精品自在线观看 | 亚洲精品国产精品乱码不卡 | 人成在线观看 | 亚洲午夜久久久久久久国产 | 日本黄色片免费 | www欧美视频 | 亚洲国产成人精品无色码 | 亚洲综人 | 亚洲午夜视频在线观看 | 伊人在线视频 | 亚洲精品在线免费看 | 国内成人自拍 | 91精品国产综合久久精品图片 | 中文字幕av在线免费观看 | 精品乱码一区二区 | 日本在线观看中文字幕 | 爱情岛论坛永久入址测速 | 国产爽爽爽 | 精品亚洲一区二区 | 91精品亚洲 | av资源在线看 | 男女互操在线观看 | 中文字幕日产av | 男人和女人搞鸡 | av午夜三片乱码少妇 | 亚洲欧洲色 | 欧美精品日韩少妇 | 色婷婷综合网 | 黄色麻豆视频 | 四川黄色一级片 | 亚洲国产一区二区三区a毛片 | 久久久青草 | 国产1区二区| 日日操夜夜 | 国产日批视频 | www.天天操 | a√天堂中文字幕在线 | 成人免费黄色大片 | 国产一二三四五区 | www.xxxx国产 | 国产第二页 | 免费在线观看日韩av | 午夜精品福利一区二区 | 久久嫩草视频 | 成人夜色 | 99在线精品视频免费观看软件 | 97潮色| 久久99成人 | 国产三区在线成人av | 欧美视频中文字幕 | avwww.| 欧美日韩在线观看一区二区 | 午夜精品在线观看 | 亚洲狠狠| 日日噜噜噜夜夜爽爽狠狠 | 国产免费av网站 | 在线观看黄色免费视频 | 色亚洲视频 | 欧美日韩成人网 | 少妇一级淫片免费放中国 | 欧美一级二级三级视频 | 日韩精品免费一区二区夜夜嗨 | 亚洲精品成人区在线观看 | 日韩精品一区二区三区国语自制 | 亚洲欧美日韩精品永久在线 | 久久午夜鲁丝片 | 狠狠艹 | 在线观看成人 | 欧美成人免费看 | 免费网站观看www在线观看 | 一级黄色片在线播放 | 午夜精品久久久久久久久久久 | 天天干妹子 | 99热1| 欧美成人一区二区三区 | 欧美成人精精品一区二区频 | 四虎中文字幕 | 日本人妻换人妻毛片 | 91免费国产| 色八区| 看毛片的网址 | 亚洲h网站| 欧美精品在线免费 | 四虎影院在线免费播放 | 午夜视频在线观看网站 | 91免费在线看 | 国产思思99re99在线观看 | 春闺艳妇(h)高h产乳 | 午夜免费小视频 | 蜜桃视频一区二区 | 亚洲狼人综合 | 国产专区一区二区 | 成人一区视频 | 天堂成人在线观看 | 中文字幕第10页 | 97精品一区二区三区 | 日本美女三级 | 黄色一节片 | 91在线视频在线观看 | 视频一区二区三区在线 | 日日碰狠狠躁久久躁蜜桃 | 中文在线视频 | 国产v亚洲v天堂无码 | 无码少妇一区二区三区 | 精精国产xxxx在线观看主放器 | 国产日韩一区 | 99久久毛片 | 黄色片视频在线观看 | 在线看片国产 | 热久久91| 91黄色免费观看 | 国内自拍网站 | 亚洲最新| 九九热只有精品 | 在线伊人网 | 欧美一区二区成人 | 免费在线中文字幕 | 亚洲欧美国产精品 | 狠狠成人 | 亚洲午夜国产 | 免费在线观看成人 | 国产又粗又黄的视频 | 九九热精品 | 成人国产免费 | 欧美三级a做爰在线观看 | 超碰在线中文字幕 | 久久一二区| 日韩一级大片 | 最近更新2019中文字幕 | 欧美在线一区二区三区 | 蜜桃久久久aaaa成人网一区 | 久久精品国产99精品国产亚洲性色 | 久久精品久久国产 | 一级特色黄大片 | 成年人网av毛片 | av一卡| 色综合图区 | 97插插插| 香蕉私人影院 | 成人黄色小视频 | 能看的av网站 | 日韩欧美在线不卡 | 久久精品国产三级 | 大学生第一次破女处视频国产 | 日本理伦片午夜理伦片 | 欧美日韩在线免费视频 | 极品少妇一区 | 亚洲a视频在线观看 | 国产在线一级片 | 国产日比视频 | 韩日在线 | 男女涩涩 | 在线观看a视频 | 美女一区二区三区 | 在线二区 | 亚州视频在线 | 天天鲁| 天天色天天射天天干 | 中文字幕亚洲情99在线 | 最新中文字幕在线观看视频 | 亚洲欧美日韩国产一区二区 | 丁香婷婷九月 | 曰批视频在线观看 | 国产欧美一区二区精品忘忧草 | 一级特黄aaa | av在线资源播放 | 深夜成人福利视频 | 亚洲欧洲视频在线 | www.激情五月 | 国产精品视频专区 | 午夜免费av | 日韩视频免费看 | 色女仆影院 | 春色免费视频 | 国产无遮挡又黄又爽又色 | 中文字幕 日本 | 国产麻豆一精品一男同 | 男女猛烈无遮挡免费视频 | 男女视频免费看 | 日韩av在线网址 | 欧美黄色免费在线观看 | 草1024榴社区成人 | 一级黄色性视频 | 性做久久久 | 国产免费脚交足视频在线观看 | 黄色在线观看免费视频 | 日韩激情在线播放 | 亚洲bb| 亚洲天堂第一 | 精品国产色 | 亚洲逼图 | 久久久久久久久久综合 | 中文字幕在线一区 | 国产爽视频 | 91激情捆绑调教喷水 | 亚洲欧美另类在线 | 青青草国产在线视频 | 在线免费观看不卡av | 免费成人看视频 | 涩涩屋视频 | 国产第一自拍 | 懂色av中文字幕 | 黄色一级黄色片 | 黄色片在线播放 | 美色视频| 日韩精品成人在线 | 野外一级片 | 国产免费一区二区三区网站免费 | 久久久久久穴 | 九九精品在线观看视频 | 国产一级做a爱免费视频 | 就操在线| 国产欧美日韩在线播放 | 欧美无遮挡高潮床戏 | 亚洲经典av| 国产免费拔擦拔擦8x在线播放 | 亚洲日本韩国在线 | 国产大奶在线观看 | 日韩欧美亚洲视频 | 日本成人免费 | 黄色一级一级 | 国产三级三级在线观看 | 真实的国产乱xxxx在线91 | 国产精品久久久久久久久免费相片 | 日韩午夜视频在线观看 | 日韩资源 | 日日干夜夜操 | 精品少妇一区二区三区免费观看 | 日韩精品久久久久久久 | 日少妇b| 中文字幕黄色av | 久久天天 | 第一页在线视频 | 色四月婷婷 | 国产免费一级 | 欧美三级在线视频 | 永久免费在线播放 | 美女视频一区二区三区 | 国产精品suv一区二区69 | 一个色在线视频 | 中文字幕天堂在线 | 久操免费视频 | 夜夜爽夜夜爽 | 一区二区三区在线免费观看 | 裸体一区二区三区 | 欧美不卡高清 | www.youjizz视频| 久久艹久久 | 五月婷婷激情视频 | 在线免费看a | 一二区精品 | 中文久久久| 高潮毛片又色又爽免费 | 一级大片视频 | 欧美成人精品一区二区三区在线看 | 久操免费在线 | 中文av字幕| 综合网色 | 综合成人在线 | 亚洲精品在线观看中文字幕 | 中文字幕第20页 | 国产视频在线一区二区 | 亚洲高清日本 | 欧美绿帽合集videosex | aaaa毛片| 国产黄色一区二区三区 | 久久视频精品 | www.亚洲天堂.com| 国产夜夜春| 精产国品一二三产区区别在线观看 | 九九在线精品视频 | 免费婷婷 | 毛片全黄 | 新av在线| 91视频色版 | 二区三区偷拍浴室洗澡视频 | 国内av网站 | 国产视频在线一区二区 | 国产伦精品一区二区三区四区免费 | 天天艹 | 久久久久一| 黄色综合| 999成人网| 美女啪啪av | 五月婷婷久 | 91伦理| 久久精品在线播放 | 成人在线免费 | 欧美日韩a级片 | 91 久久| 91视频a | 成人小视频免费 | 国产成人专区 | 中国毛片a | 在线观看成人黄色 | 久久精品欧美一区 | 欧美无极品 | 欧美成在线观看 | 国产毛片一区二区三区va在线 | 福利网址在线观看 | 在线观看视频色 | 成人免费黄色网址 | 在线播放视频高清在线观看 | 欧美日韩少妇 | 波多野结衣免费看 | 久久综合中文字幕 | 欧美成在线| 三级国产三级在线 | 黄网站免费在线观看 | 国产精品福利一区二区三区 | 男人天堂你懂的 | 日韩第九页 | 99国产在线视频 | sm在线看| 色哟哟在线观看视频 | 色就是色综合 | 91免费版黄| 性高潮久久久久久久久久 | av国产一区 | 超碰在线| 久久久久精彩视频 | 澳门av在线 | 精品免费在线视频 | 视频在线一区二区三区 | 久久天堂精品 | 啪视频在线 | 国产无遮挡呻吟娇喘视频 | 亚洲一区中文字幕 | 亚洲欧美中文字幕 | 午夜婷婷在线观看 | 成人欧美一区二区三区在线播放 | 日韩久久一区二区三区 | 久久这里都是精品 | 成年人免费毛片 | 日本成人免费观看 | 四虎图库 | 成人做爰66片免费看网站 | 国产精成人品免费观看 | 国产自产高清不卡 | 欧美成人第一页 | 亚洲欧美一区在线观看 | 日韩中出 | 在线观看av毛片 | 一区二区视频免费在线观看 | 巨乳在线播放 | 成人性生交大片免费看96 | 亚洲六月丁香色婷婷综合久久 | 午夜a视频| av爱爱| 肉色超薄丝袜脚交一区二区 | 在线你懂 | 欧美日韩精品二区 | 国产黄a三级三级三级看三级男男 | 国产乱人伦偷精品视频不卡 | 97国产在线视频 | 日韩一级一级 | 在线看尤物 | 天天玩夜夜操 | 91视频免费在线 | 91国语对白 | 一级一级特黄女人精品毛片 | 亚洲一区欧美一区 | 91精品国产自产 | www.伊人.com | 中文在线日韩 | 香蕉在线网站 | 一区二区三区美女视频 | 粉嫩av一区二区夜夜嗨 | 青青草手机视频在线观看 | 男女激情啪啪 | 91久久精品日日躁夜夜躁国产 | 天天做天天爱天天操 | 夜夜躁天天躁很 | 99久久精品久久久久久动态片 | 成年人视频网 | 97中文字幕 | 精品久久久久久久久久久国产字幕 | 69天堂 | 天天cao在线| 日韩精品视频在线看 | 二区影院| 久久久国产精品视频 | 婷婷av一区二区三区 | 免费国产视频在线观看 | 欧美a一级| 国产成人精品一区二区三区免费 | 亚洲成人第一页 | 一本色道精品久久一区二区三区 | 日本久久综合 | 在线一区观看 | 亚洲国产精品嫩草影院久久av | 色婷婷香蕉在线一区二区 | 亚洲欧美综合一区二区 | 国产成人精品网 | 人人爽人人插 | 视频在线一区 | 国产一级淫片a视频免费观看 | 日韩成人午夜 | 久久久视| 伦理片一区二区三区 | 最近中文字幕免费视频 | 亚洲一区二区三区视频在线 | 三级a视频 | 美国一级大黄一片免费中文 | 国产美女自拍视频 | 少妇色欲网 | 久草视频在线免费 | 77777av| 中文字幕一区二区三区视频 | 国产婷婷综合 | www.狠狠插 | www三级免费 | 亚洲人成小说 | 国产伦精品一区二区三区免费优势 | 亚洲精品国产一区二区三区四区在线 | 69色综合| 伊人艹 | 91嫩草欧美久久久九九九 | 成人天堂资源www在线 | 国产婷婷一区二区三区久久 | 插插插日日日 | 国产精品成人久久久久久久 | 一本一道久久a久久精品蜜桃 | 免费看的一级片 | 91久久爱 | 91看大片| 精品国精品国产自在久不卡 | 欧美大黄| 午夜视频导航 | 777理伦三级做爰 | 午夜一区视频 | 国产精品视频在线播放 | 国内精品嫩模av私拍在线观看 | 欧美成a | 91视频看看 | 91天堂网| 国产精品女教师久久二区二区 | 久久久天天 | 精品久久久久一区二区 | 欧美激情视频网站 | 奇米第四色777 | 51成人做爰www免费看网站 | 懂色av蜜臀av粉嫩av分 | 亚洲国产精品嫩草影院 | 欧美午夜一区 | 亚洲国产精品99久久久久久久久 | 久久天天躁狠狠躁夜夜av | 韩国av一区二区 | 欧美激情午夜 | 色老二导航| 欧美在线免费观看视频 | 在线看免费av| 在线国产黄色 | 亚洲成人a∨ | 亚洲精品激情 | 欧美黄色一级 | 国产精品午夜未成人免费观看 | 国产精品久久久久毛片 | 国产精品久久欧美日韩 | 免费精品视频一区二区三区 | 日韩精品视频一区二区三区 | av伊人久久 | 国产黄色大片在线观看 | 国模私拍在线 | 日韩黄色网址 | 国产午夜精品视频 | 国产在线一级片 | 婷婷91 | 琪琪午夜伦理影院7777 | 亚洲一区二区激情 | 国产男女av| 久久精品一本 | 伊人www| 五月天激情婷婷 | 久久99亚洲精品 | 一级片大全 | 欧美久久激情 | 一区中文字幕 | 一本色道久久88综合日韩精品 | 日韩av免费在线 | 国产丰满农村老妇女乱 | 天天射天天色天天干 | 国产精品久久久久久久久久久久久久久久久 | 成人黄色免费网站在线观看 | 在线日本中文字幕 |