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

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

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

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

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

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

Angular概述

Angular 是谷歌開發的一款開源的 web 前端框架,基于 TypeScript ?!鞠嚓P教程推薦:《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)

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

何時觸發臟值檢測:瀏覽器事件(click、mouseover、keyup等)、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 () 的元數據中。

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

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

  • 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 ,只在根模塊中導入,并且整個應用只需導入一次,不用在其他模塊導入

在構造函數中注入HttpClient,get/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表單

模版驅動表單

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

如果有非?;镜谋韱涡枨蠛秃唵蔚侥苡媚0骞芾淼倪壿?,就使用模板驅動表單

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

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

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

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

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

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

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

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

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

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

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

首先加載 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號
主站蜘蛛池模板: 91在线亚洲 | 性色浪潮av| 大帝av| 青青成人 | 黄色a视频 | 日韩国产欧美在线观看 | 午夜18视频在线观看 | 夜夜操操 | av网站有哪些 | 精品久久在线观看 | 中文字幕第4页 | 亚洲永久在线观看 | 资源av| 国产亚洲欧美视频 | 亚洲成人v | 99少妇| 国产精品色婷婷99久久精品 | 欧美视频三区 | 国产精品久久久久久久久搜平片 | 国产黄在线 | 日韩精品一二三 | 国产不卡精品视频 | 日日射夜夜操 | 又长又硬又粗一区二区三区 | 日韩一级久久 | 全部免费毛片在线播放一个 | 夜夜嗨av禁果av粉嫩avhd | 欧美视频久久 | 精品三级视频 | 中国特级黄色一级片 | 午夜免费看| 亚洲一级黄色片 | 少妇导航av | 欧美日韩一区在线观看 | 国产尤物在线视频 | 天天爽夜夜操 | 福利影院在线观看 | 欧美成人三级在线观看 | 综合网婷婷 | 黄色片小视频 | 国产精品三级视频 | 一级片免费播放 | 欧美极品喷水 | 色视频在线免费观看 | 亚洲a成人 | 2020国产在线| 中国肥胖女人真人毛片 | 性色免费视频 | 欧美 日韩 国产 在线 | 亚洲图片 欧美 | 日本久久黄色 | 永久免费精品影视网站 | 国产夜夜夜| 中文在线一区二区 | 成人网战 | 亚洲精品国产精品乱码视色 | 狠狠干五月 | 一本一道久久a久久精品综合 | 97久久人澡人人添人人爽 | 国产在线操 | 亚洲图片自拍偷拍区 | av丁香 | 意大利av在线 | 国产精品13p | 东方av伊甸园 | 久草色视频 | 欧美丰满美乳xxx高潮www | 国内自拍视频在线播放 | 国产精品色悠悠 | 夜夜天天操 | 国产视频91在线 | 四虎啪啪 | 欧美第三页 | 欧美日韩在线看 | 精品乱码一区二区三区 | 三级色网 | 成人欧美在线观看 | 国产女优在线播放 | eeuss一区二区 | 五月婷婷开心 | 天天综合久久综合 | 特级一级片 | 六月丁香激情 | 手机看片1024日韩 | 一本到免费视频 | 顶破超薄肉色丝袜进入 | 性生活视频软件 | 婷婷午夜精品久久久久久性色av | 91在线视频在线观看 | 国产一区二区三区免费播放 | 99一区二区三区 | 亚色视频在线观看 | 成人午夜影视在线观看 | 久草资源在线 | 77777av| 劲爆欧美第一页 | 97在线观看视频 | 97毛片| 久久久www成人免费毛片 | 亚洲天堂2012 | av在线播放一区 | 国产三级欧美三级日产三级99 | 久草日韩在线 | 久久91网 | 黄色理伦片 | 欧美日韩免费网站 | 91网页入口 | www.色网站 | 天堂中文网在线 | 亚洲人网站 | 精品久久久久久国产 | 日韩一区二区精品视频 | 99热精品在线| 波多野结衣在线一区二区 | 性视频黄色 | 日日爱666| 天堂免费av | 午夜网站在线 | 亚洲免费观看视频 | 国产性一乱一性一伧一色 | 韩国三级中文字幕hd浴缸戏 | 中文字幕国产一区二区 | 国产精品视频一二三区 | 天天干天天操天天插 | 免费播放毛片 | 九九av在线| 五月婷婷丁香综合 | 国产 xxxx | 在线不卡亚洲 | 欧美日韩亚洲一区二区三区 | 国产淫语对白 | 我要看18毛片 | 亚洲激情一区二区 | 色噜噜狠狠狠综合曰曰曰88av | 综合色站导航 | 国产超碰人人 | 国产无遮挡免费视频 | 黄色污网站在线观看 | 亚洲午夜免费 | 成人免费视频一区二区三区 | 亚洲人成激情在线播放国 | 亚洲精品黄 | 手机看片欧美日韩 | 99插插插| 国产a区| 91蝌蚪91九色 | 国产精品日韩一区 | 日本xxxxxxxxx | www.好了av | 黄色性视频网站 | 最新中文字幕在线观看视频 | 国产淫语对白 | 午夜精品久久久久久久91蜜桃 | 亚洲精品久久久蜜桃动漫 | 天天看毛片 | 亚洲一级大片 | 亚洲自拍偷拍综合 | 巨物撞击尤物少妇呻吟 | 不卡的毛片| 久久久久久影院 | 美女三区 | 中文字幕无人区二 | 欧美成人自拍 | 亚洲国产视频在线观看 | 九九免费精品视频 | 亚洲小视频在线 | 91偷拍精品一区二区三区 | 成人你懂的 | 国产白嫩受无套呻吟 | 91国偷自产中文字幕久久 | 日韩成人av在线播放 | 91精品久 | 波多野结衣中文字幕一区 | 亚洲欧美另类一区 | 国产网站大全 | 爱如潮水3免费观看日本高清 | 中国在线观看免费高清视频播放 | 久色成人 | 在线观看av免费 | 免费观看在线观看 | 亚洲精品乱码久久久久久蜜桃动漫 | 亚洲综合大片69999 | 警察高h荡肉呻吟男男 | 欧美中出 | 国产精品色哟哟 | 久久久黄色网 | 亚洲欧美韩国 | 精品国产99 | 日韩av在线资源 | 99草在线视频 | 骚婷婷 | 制服.丝袜.亚洲.中文.综合懂 | 久久人人艹| 高潮疯狂过瘾粗话对白 | 黄色在线一区 | 日韩精品专区 | 国产一级在线观看视频 | 欧美狠狠操 | 色一情一乱一乱一区91av | 亚洲天堂中文字幕在线 | 久久久国产高清 | 色综合久久天天综合网 | 最近中文字幕在线播放中 | 午夜在线视频免费 | 探花视频在线版播放免费观看 | 国产精品久久网 | 这里只有精品在线观看 | av黄色在线| 国产高清精品在线 | 涩涩视频软件 | 日韩乱码一区二区三区 | av不卡在线看| 99精品一区二区 | 国产精品视频免费丝袜 | 一区二区三区四区蜜桃 | 天天拍天天操 | 日韩在线一区二区三区四区 | 免费看日批视频 | 婷婷色在线视频 | 在线看网站 | 99热2| 性生活毛片 | 91精品国产综合久久香蕉的特点 | 天堂999| 久操综合 | 亚洲xxx视频| 日本在线一区二区三区 | 日本在线中文字幕专区 | 国产中文一区 | 66m—66摸成人免费视频 | 国产绿帽刺激高潮对白 | 国产igao为爱做激情在线观看 | 午夜特级毛片 | 亚洲网站av | 欧美另类视频在线观看 | 色999日韩 | 可以免费观看的av网站 | 亚洲码国产精品高潮在线 | 久久九九色 | 亚洲国产精品成人综合久久久久久久 | 97人人艹 | 黄色小视频在线看 | www.久久久久.com | 最新超碰 | 欧日韩在线观看 | 日韩精品中文字幕一区 | 五月婷网站 | 国产999精品久久久久久 | 肉色欧美久久久久久久免费看 | 丁香花免费高清完整在线播放 | 久久久久亚洲av成人毛片韩 | 五月婷婷丁香六月 | www.日日| 国产又粗又猛又黄又爽的视频 | 性福利影院 | 9l视频自拍蝌蚪9l视频 | 羞羞羞网站 | 蜜桃精品在线观看 | 自拍偷拍亚洲第一 | 日韩精品在线观看免费 | 艳母动漫在线播放 | 日日网 | 午夜看片网站 | 日韩国产欧美一区二区 | 欧美日韩国产高清 | 亚洲视频精品在线 | 精品乱子伦一区二区 | 91视频中文字幕 | 一级黄色片大全 | 91国偷自产中文字幕久久 | 超碰人人国产 | 日韩欧美视频在线播放 | 日本少妇吞精囗交 | 激情综合网五月 | 91色香视频 | 国产精品久久久av | 国产免费av一区 | 91看片淫黄大片 | 色婷婷综合久久久中文字幕 | 一级啪啪片 | 经典一区二区 | 成人黄色激情小说 | 日韩欧美综合在线 | av777777 | 中文字幕一区二区三区精品 | 日本三级中文字幕 | 8x8ⅹ成人永久免费视频 | 国产网址你懂的 | 亚洲综合15p | 懂色av蜜臂av粉嫩av | 中文字幕无人区二 | 久久天天躁狠狠躁夜夜97 | 国产三级自拍 | 在线免费一级片 | 亚洲伦理在线视频 | 91福利在线导航 | 日韩欧美在线免费 | 97久久久久 | 久久亚洲精精品中文字幕早川悠里 | 欧美成人久久 | 激情综合久久 | 欧美一本 | 午夜激情国产 | 国产激情免费 | 嫩草视频在线观看免费 | 中文字幕丰满人伦在线 | 偷拍青青草| 少妇av在线 | 亚洲一区在线观看视频 | 一卡二卡在线观看 | 插吧插吧综合网 | 国产床上视频 | 91美女视频在线观看 | 亚洲 国产 另类 精品 专区 | 国产精品一区二区三区不卡 | 国产精品黄色av | 五月婷婷爱 | 青青艹在线视频 | 中文视频在线观看 | 久热精品视频在线 | 日韩福利视频一区 | 婷婷丁香综合 | 日韩精品视频在线观看免费 | 久久久久久国产精品免费 | 天天色综网 | va视频在线观看 | 老汉色老汉首页av亚洲 | 亚洲最大的av网站 | ww欧美| 久久成人激情 | av2014天堂网 | 91私拍 | 男人天堂视频在线 | 久久综合操 | 97免费在线视频 | 毛茸茸日本熟妇高潮 | 亚洲午夜片 | 老司机午夜精品 | 伊人色综合久久天天 | 午夜偷拍福利视频 | 欧美极品少妇xxxxⅹ免费视频 | 日本精品入口免费视频 | 中文字幕日韩精品视频一区视频二区 | 天天操综合网 | 黄色特级视频 | 九色丨蝌蚪丨少妇调教 | 免费观看成年人视频 | 99久久婷婷国产综合精品青牛牛 | 日本欧美在线视频 | 黄色1级视频 | 91精品一区二区三区在线观看 | 婷婷俺来也| 91色国产| 在线看片日韩 | 中文字幕 国产精品 | 国产一区福利 | 激情av中文字幕 | 国产精品高潮呻吟久久av免费动漫 | 都市激情校园春色亚洲 | 中文免费视频 | 国产综合影院 | 色播欧美 | 精品国产一区二区三区久久久久久 | 六月激情婷婷 | 日韩不卡一区二区 | 手机看片福利一区 | av黄色免费 | 91激情网站 | 天天射天天舔 | 免费欧美一级 | 夜夜操夜夜操 | 99热激情 | www.久久成人| 日本一级黄色录像 | 国产一级片免费视频 | 亚洲精品水蜜桃 | 日韩免费观看 | 123成人网| 亚洲另类一二三区 | 亚洲精品一区在线观看 | 中文字幕男人天堂 | 在线观看黄网 | 国内精品偷拍视频 | 91精东传媒理伦片在线观看 | 日韩精品欧美在线 | 亚洲精品视频一区二区三区 | 久草资源在线观看 | 久久小草| 久久精品视频国产 | 中文一二三区 | 国产精品第九页 | 日日操天天操 | 91久热| 亚洲国产免费 | 国产精品国产三级国产在线观看 | 天堂在线中文字幕 | 国产精品成人aaaaa网站 | 日本免费在线观看视频 | 国产精品第72页 | 日韩欧美成 | 综合激情自拍 | 国产国拍精品亚洲 | 国产精品久久久久久久久借妻 | 国产婷婷久久 | 亚拍一区 | 日日操日日操 | 欧美精品成人久久 | 欧美激情啪啪 | 97av超碰 | 亚洲综合图区 | 亚洲国产视| 男女国产精品 | 国产精品久久久久久久久久了 | 校园春色av | 国产人澡人澡澡澡人视频 | 久久五月激情 | 精品国产xxx | 夜夜爽狠狠澡97欧美精品 | www.99精品 | 人人爽人人爽人人片av | 国产天天操 | 日日干天天| 免费一级大片 | 成人爽爽爽 | 国产在线不卡av | 国产一级免费观看 | 91精品视频在线 | 国产91大片 | av九九九| 亚洲日本久久 | 中文字幕 亚洲视频 | 亚洲操 | 一级aaaa毛片| 亚洲污片 | 一区二区免费 | 在线精品亚洲欧美日韩国产 | 国产乱码精品一区二区三区五月婷 | 男人天堂手机在线观看 | 亚洲在线a| 久草手机在线 | 伊人激情网 | 日韩一区二区中文字幕 | 欧美亚一区二区三区 | 亚洲欧美激情一区二区三区 | 91超碰免费 | 国产黄色自拍 | 欧美中文一区 | 丰满少妇高潮在线观看 | 污污视频在线观看免费 | 国产白浆视频 | 日韩av成人在线 | 欧美调教视频 | 亚洲精品 欧美 | 日韩av在线播放观看 | 综综综综合网 | 狼人伊人av| 欧美日韩aa | 成年人黄色小视频 | 国产在线日韩 | 亚洲第一香蕉网 | 欧美视频在线观看一区二区三区 | 福利二区 | 天天干夜夜草 | 午夜av成人 | 国产免费福利视频 | 最新国产精品精品视频 | 久久草视频在线 | 欧洲亚洲精品 | 91小视频 | 欧美精品入口蜜桃 | 亚洲另类xxxx | 色桃av| 亚洲国产免费 | 久久久96 | 亚洲性视频 | 性喷潮久久久久久久久 | 亚洲天堂影音先锋 | 黄色91免费 | 在线观看国产日韩 | wwwav视频 | 国产又大又黄的视频 | 新婚夫妇白天啪啪自拍 | 黄色精品一区二区 | 在线免费观看黄色片 | 人人爽人人爱 | 久久香蕉精品视频 | 在线免费观看一区 | 想要xx在线观看 | 奇米影视盒 | 新毛片基地 | 91吃瓜在线| 在线看黄网址 | 毛片大片 | 成人在线中文字幕 | 日本午夜大片 | 丰满少妇一区二区三区 | 国产精品第9页 | 免费av网址大全 | 成人免费毛片果冻 | 国产精品国产精品国产专区不片 | www激情网 | 激情五月婷婷网 | 一级黄色片一级黄色片 | 97在线观看视频 | 冈本视频在线观看 | 污污网站在线 | 亚洲视频黄| 亚洲国产激情 | 亚洲欧美日韩国产精品一区午夜 | 亚洲婷婷丁香 | 最新国产精品精品视频 | 国产一级大片 | 香蕉精品视频在线观看 | 看全黄大黄大色大片美女 | 日日夜夜综合网 | 日韩毛片 | 国产极品久久久 | 欧美视频在线观看一区二区 | 国产婷婷色综合av蜜臀av | 国产精品久久久久久久裸模 | 天堂色综合 | 久久国产精品一区二区 | 欧美偷拍一区二区三区 | 婷婷六月综合 | 日韩黄色一级大片 | 欧美性xxxxxx | 国产精品福利在线观看 | 在线色国产 | 狠狠躁18三区二区一区传媒剧情 | 欧美一区二区三区免费观看 | 齐天大性床战铁扇公主 | 日韩成人免费观看 | 精品国产乱码久久久久久蜜臀网站 | 国产激情一区二区三区 | 99这里有精品视频 | 国产三级一区二区三区 | 亚洲一区二区三区成人 | 瑟瑟综合 | 国产亚洲精品久久久久5区 中国女人啪啪69xxⅹ偷拍 | 精品日韩一区二区三区 | 天天干天天狠 | 性猛交xxxx乱大交孕妇2 | 作爱视频在线 | 久久国产露脸精品国产 | 成人有色视频 | 亚洲国产成人综合 | 中文字幕5页| 久久99精品久久久久久 | 五月婷网站| 免费av一级片 | 青青青国产视频 | 蜜桃视频一区二区三区 | 综合一区二区三区 | 永久免费的网站入口 | 国产一二三四在线 | 性高潮久久久久 | 一区二区不卡视频 | 亚洲精品中文字幕视频 | 精精国产xxxx视频在线野外 | 91禁动漫在线 | 日本在线免费观看视频 | 自拍露脸高潮 | 久久久96| 在线看片日韩 | 亚洲国产精品毛片 | 日韩精品观看 | 丰满雪白极品少妇流白浆 | 午夜操一操| 日韩在线视频二区 | 嫩草伊人| 一级做a爰片性色毛片 | 99九九久久 | av在线导航 | 免费99视频| 国产日比视频 | 天堂在线官网 | 九九热色 | 一级免费大片 | 精品午夜一区二区三区在线观看 | 性欧美亚洲xxxx乳在线观看 | 欧美三级a做爰在线观看 | av在线播放免费 | 国产96在线 | 日本午夜小视频 | 亚洲精品乱码久久久久久黑人 | 精品一区二区三区日韩 | 日韩在线视频观看 | 精品视频免费在线观看 | 国产精品久久影视 | 国产精品毛片av | 国产欧美在线看 | 尤物在线 | a级片黄色| 亚洲精品一区二区三 | 人人插人人干 | 色交视频 | 午夜美女福利 | 黄色片小视频 | 国产新婚疯狂做爰视频 | 亚洲911精品成人18网站 | 色婷婷免费视频 | 在线亚洲欧美 | 性生活视频在线播放 | 久久婷婷av | 国产高潮国语对白精品视频网站 | 美国av导航 | 毛片天堂 | 亚洲免费一级 | 岛国av噜噜噜久久久狠狠av | 国产成人av一区二区三区在线观看 | 91网站在线免费观看 | 国产一二三四五区 | 一级香蕉视频在线看 | 久久免费视频99 | 精品九九九九九 | 中文天堂在线视频 | 日韩福利在线观看 | 红桃视频91 | 中文字幕免费观看 | 亚洲精品欧美精品日韩精品 | 伊人久久久久久久久久 | 国产日本视频 | 日本特级黄色片 | 69久久| 91成人免费看片 | 青青国产视频 | 性高潮久久久久久久久 | 国产欧美一区二区三区在线看蜜臂 | av无线看 | 男女搞黄网站 | 91成人免费在线观看 | 日批视频免费在线观看 | 三级免费毛片 | 亚洲成人一二区 | 337p粉嫩大胆噜噜噜亚瑟影院 | 一级国产片 | 最近2019中文字幕大全视频10 | 福利一区二区 | 久久99久久99精品蜜柚传媒 | 98国产精品综合一区二区三区 | 欧美影院在线观看 | 国产一级理论 | 狠狠鲁狠狠干 | 国产精品久久久久久在线 | 黄色网在线看 | 天天干夜夜夜 | 国产永久精品 | 国产做受高潮漫动 | 萌白酱一区二区 | 国产精品特级毛片一区二区三区 | 国产精品久免费的黄网站 | www.天堂av | 91精品国产麻豆国产自产在线 | 依人在线观看 | 国产精品xxx在线观看 | 日本不卡视频在线 | 乳孔很大能进去的av番号 | 久久国产精品一区二区 | 成年免费在线 | 日本三级欧美三级 | 天天综合入口 | 国内精品嫩模av私拍在线观看 | 免费av不卡 | av观看免费 | 亚洲妇女av| 齐天大性床战铁扇公主 | 亚洲欧美少妇 | www.超碰在线 | 国产66精品久久久久999小说 | 一级不卡毛片 | 香蕉视频久久久 | 国产精品第四页 | 俺也去在线视频 | 男女做事网站 | 日本免费在线观看视频 | 亚洲国产二区 | 日韩毛片一级 | 欧洲av片| 黄色精品视频 | 日本久久网| 亚洲伦乱| 亚洲欧美自拍偷拍视频 | 五月激情婷婷网 | 精品久久久精品 | 亚洲成人av一区二区 | 青青青免费在线视频 | 午夜精品三级久久久有码 | 亚洲蜜桃视频 | 人超碰 | 涩涩涩涩av| 成人午夜在线观看视频 | 一区二区激情 | 亚洲一线二线三线久久久 | 国产精自产拍久久久久久蜜 | 狠狠天堂| 精品一区二区三区精华液 | 色呦呦精品 | 黄色成人在线视频 | 成人免费在线网站 | 中文字字幕 | 激情伊人网 | 欧美中文字幕在线 | 蜜臀麻豆 | 日韩av一二三区 | 黄色一级网址 | 国产高清自拍视频 | 永久91嫩草亚洲精品人人 | 五月天综合激情 | 九九色网 | 999久久久国产精品 欧美大片一区二区三区 | 一区二区精品区 | 高清av一区 | 五月综合色 | 非洲一级片| 91在线免费视频 | 亚洲性片| 午夜亚洲国产 | 亚洲欧美日韩中文在线 | 日吊视频| 天天草天天射 | 公车激情云雨小说 | 亚洲精品在线网站 | 国产视频亚洲精品 | 国产特级黄色录像 | 欧美一级淫片免费视频魅影视频 | 91青青操 | 国产精品久久久久毛片软件 | 成人av番号网 | 日本www| 国产精品久久久久久久久图文区 | 国产中文字幕亚洲 | 这里只有精品在线播放 | 91欧美日韩 | 久夜精品 | 一本久久道 | 日韩中文字幕在线免费观看 | 久久久午夜精品 | 91丨porny丨在线中文 | 小宵虎南在线观看 | 欧美在线一级片 | 五月天综合社区 | 91免费高清视频 | av在线播放观看 | 国产视频不卡 | 日韩亚洲一区二区 | 国产乡下妇女做爰 | 在线视频观看国产 | 看特级毛片 | 91一区二区三区在线观看 | 欧美综合视频在线观看 | 华人在线视频 | 色5月婷婷 | 伊人91视频 | 欧美午夜不卡 | 国产男女啪啪 | av在线不卡免费观看 | 国产在线观看www | 欧美成人三级 | 亚洲国产精品久久久久久久 | 黄色三级网站 | 成人h动漫精品一区 | 亚洲欧美综合一区二区 | 欧美精品乱码视频一二专区 | 黄色在线观看视频 | 欧美在线视频网站 | 欧美精品在线视频观看 | 91在线免费看 | 欧美精品久久久久a | 一级日韩毛片 | 人人爽人人草 | 欧美在线色图 | 欧美综合激情 | 黄色一级在线 | 欧美中文字幕在线观看 | 香蕉综合网| 成人在线小视频 | 亚洲视频一区二区在线观看 | 亚洲乱码国产乱码精品精不卡 | 久久精品高清 | 国产 日韩 欧美 精品 | 日本乱码一区二区 | 亚洲婷婷av| 伦理片波多野结衣 | 免费黄色网址大全 | 午夜视频在线看 | 91久久爽久久爽爽久久片 | 欧美 亚洲 一区 | 亚洲午夜精品一区二区 | 国产剧情精品在线 | 国产a久久麻豆入口 | 星空大象在线观看免费高清 | 7777精品久久久久久 | 91区 | 95看片淫黄大片一级 | 免费超碰在线 | 亚洲成av人片在www色猫咪 | 一级片免费看视频 | 在线永久免费观看 | 三级a做爰全过程 | 成人久久大片91含羞草 | 少妇一级淫片免费看 | 午夜寂寞影院在线观看 | 欧美亚洲| 成年人在线播放视频 | 综合色网站 | 中文天堂在线中文 | 超碰免费在线播放 | 中文字幕精品久久一二三区红杏 | 91成人国产 | 专业操老外 | 亚洲天堂手机版 | 国产成人免费观看 | 国产精彩视频在线 | 一区二区精品视频在线观看 | 一区二区精品视频在线观看 | 日韩精品无码一区二区三区 | 色婷婷九月| 日韩xxx视频| 久久午夜影院 | 米奇7777狠狠狠狠视频 | 在线免费观看a级片 | 日本不卡一 | 午夜精品久久久久久久96蜜桃 | 色哟哟国产精品色哟哟 | 亚洲成年人网站在线观看 | 在线观看黄色动漫 | 国产黄三级三级三级三级一区二反 | 青春草视频在线免费观看 | 日韩欧美精品在线观看 | 色无极亚洲影院 | 久久精选视频 | 亚洲字幕在线观看 | 男女猛烈无遮挡 | 日本xxxxxwwwww | 992tv在线成人免费观看 | 精品一区久久 | 国产一级淫片免费 | 欧美在线网址 | 日韩视频一区二区在线观看 | 日本高清不卡二区 | 黄色小说网站在线观看 | 免费看色 | 中文字幕一区二区三区不卡 | 亚洲啪啪网站 | 国产激情一区 | 欧美黑人精品 | 亚洲wwwwww | 欧美在线高清 | 看一级黄色大片 | 国产精品亚洲成在人线 | 可以看av的网站 | 韩国理论午夜 | 美日韩免费视频 | 国产黄色一区 | 中文字幕在线精品 | 天天操天天舔天天干 | 成人欧美一区二区三区在线观看 | 国产天堂第一区 | 国产山村乱淫老妇av | 最近2019中文字幕大全第二页 | 亚洲在线第一页 | 国产综合区 | 91丨九色丨丰满 | 国产精品美女久久久 | 激情五月激情综合网 | 久在线视频 | 国产91调教 | 99色资源 | www.性欧美| xxx视频在线观看 | 欧美手机在线视频 | 国产人伦精品一区二区三区 | 自拍一级片 | 日本少妇色视频 | 亚洲欧美一区二区三区情侣bbw | 找个毛片看看 | wwwxx国产在线观看 | 午夜美女福利 | 欧美亚洲另类图片 | 丰满少妇毛片97级无遮挡 | 理论av| 插插插91 | 国产精品日韩一区 | 中文字字幕在线中文乱码 | 亚洲首页在线 | 在线日韩精品在线 | 九九精品在线视频 | 免费一级片网站 | 最新99热 | 天天干女人 | 日韩不卡高清视频 | 久射久| 国产视频在线看 | 国产成人精品一区二区三区在线 | 国产另类视频 | 亚洲综合视频一区 | 中年夫妇大白天啪啪高潮不断 | 欧美成人精品激情在线视频 | 九色国产视频 | 福利视频亚洲 | 久久视频精品 | 美国黄色一级大片 | 国产日产欧美 | av网站一区二区三区 | 久久久久久久久91 | 国产二区三区 | 亚洲欧美精品一区二区三区 | 我要看一级黄色片 | 少妇人妻一级a毛片 | 欧美一级免费片 | 国产h在线 | 成人在线免费观看视频 | 热久久久久久久 | 亚洲污片| 欧美一区二区三区影院 | 国产91传媒| 国产永久在线观看 | wwwxx国产| 国产五月婷婷 | 麻豆精品视频在线 | 久久欧美视频 | 午夜宅男影院 | 国产成人在线观看网站 | xxxxxhd亚洲人hd| 成人免费入口 | 极品少妇露脸一区二区 | 亚洲痴女 | 亚洲在线视频观看 | 偷拍亚洲综合 | 欧美极品在线 | 亚洲欧美日韩免费 | 男女免费网站 | av中文字幕第一页 | 美女视频污 | 中文在线а√在线8 | 欧美日韩精选 | 亚洲少妇一区 | 亚洲成在线观看 | 用力使劲高潮了888av | 国产精品11p | 碰超在线 | 91麻豆精品国产91久久久久久 | 国产亚洲精品久久久久动 | www.三级 | 久久青青草原 | 色视频在线播放 | 高潮中文字幕 | 亚洲天堂免费视频 | 国产清纯白嫩初高中在线观看性色 | 国产精品二区在线观看 | 日韩精品免费在线观看 | 久久网中文字幕 | 毛片基地免费 | 日韩福利一区二区 | 免费观看亚洲 | 欧美成人免费在线 | 一级片在线免费观看视频 | 国产一级网站 | 精品在线91 | 亚洲成a人片 | 色综合a| 精品网站999 | 亚洲精美视频 | 一级二级三级视频 | 日本a级无毛 | 六月婷婷激情 | 黄av在线| 91福利社在线观看 | 思思久久久 | a色网站| 一集毛片 | 国产福利免费观看 | 亚洲国产中文在线 | 亚洲精品一二三四 | av毛片在线免费看 | 日本大胆裸体做爰视频 | 中国女人av | 四虎午夜 | 亚洲不卡网 | 国产情侣啪啪 | 欧洲毛片 | 正在播放91| 黄色小说在线观看视频 | 亚洲一级精品 | 午夜影院欧美 | 噜噜噜久久久 | 夜夜小视频 | www.夜色 | 中文字幕精品一二三四五六七八 | 国产精品婷婷午夜在线观看 | 欧美在线播放一区 | 国产精品亚洲а∨天堂免在线 | 亚洲国产精一区二区三区性色 | se婷婷 | 午夜免费大片 | 日韩干 | 亚洲一区欧美 | 亚洲人体av | 水蜜桃91|