Angular 入坑 01

1. 目錄結(jié)構(gòu)

e2e —— 自動(dòng)化測(cè)試
src —— 根目錄
app —— App
app-routing.module.ts —— 項(xiàng)目路由配置文件
app.component.html —— App模板文件
app.component.scss —— App樣式文件
app.component.spec.ts —— 單元測(cè)試文件
app.component.ts —— App組件的配置文件
app.module.ts —— NgModule配置溫江
assets —— 放置靜態(tài)資源
environments —— 放置環(huán)境配置
index.html —— 單頁面應(yīng)用的入口模板
main.ts —— 項(xiàng)目入口
styles.scss —— 全局樣式表
test.ts —— 測(cè)試文件
.browserslistrc —— 瀏覽器兼容性配置
.editorconfig —— 瀏覽器格式化配置
.gitignore —— git忽略配置
angular.json —— Angular配置
karma.conf.js —— 自動(dòng)化測(cè)試配置
package-lock.json —— Webpack 依賴鎖定配置
package.json —— 項(xiàng)目依賴配置
README.md —— readme文件
tsconfig.app.json —— TypeScript配置文件
tsconfig.json —— App對(duì)于TypeScript檢測(cè)的配置文件
tsconfig.spec.json —— TypeScript檢測(cè)的配置文件

2. Angular CLI

2.1 初始化AngularCLI

安裝 Angular CLI

npm install -g @angular/cli

創(chuàng)建一個(gè) Angular 應(yīng)用

ng new my-app

運(yùn)行應(yīng)用

ng serve --open

2.2 組件介紹以及組件創(chuàng)建

2.2.1 組件

組件的特征在于可以用于執(zhí)行單個(gè)任務(wù)的代碼塊??梢詮拇a(類)中導(dǎo)出值。Angular應(yīng)用程序被稱為組件,可以使用許多組件構(gòu)建應(yīng)用程序。Angular的基本組件是可以從組件中導(dǎo)出的組件類

import { Component } from '@angular/core';
// 使用 @Component 裝飾器聲明當(dāng)前這個(gè)類是一個(gè)組件
@Component({
  // 當(dāng)前組件渲染的選擇器
  selector: 'app-root',
  // 對(duì)應(yīng)渲染的組件的模板
  templateUrl: './app.component.html',
  // 加載到當(dāng)前模塊的樣式文件,可以接受多個(gè)樣式表,是數(shù)組形式的
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  // 模板數(shù)據(jù)(可以使用插值表達(dá)式渲染到頁面中)
  title = 'my-app';
}
2.2.2 創(chuàng)建組件

使用快速創(chuàng)建命令自動(dòng)生成在 app.module中創(chuàng)建組件,其中ComponentName是組件名

ng g c ComponentName

新生成的組件目錄中
test-component.component.html —— 組件模板文件
test-component.component.scss —— 組件樣式文件
test-component.component.spec.ts —— 組件單元測(cè)試文件
test-component.component.ts —— 組件Js文件

3. 基本應(yīng)用

3.1 插值表達(dá)式

插值表達(dá)式用法基本同 Vue 中的插值表達(dá)式
test-component.component.ts

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

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

  name:String = 'Alex'

  constructor() { }

  ngOnInit(): void {
  }

}

test-component.component.html

<p>test-component works!</p>
<div>{{ name }}</div>

3.2 屬性綁定

test-component.component.ts

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

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

  name:String = 'Alex'
  h3Dom:Boolean = true
  constructor() { }

  ngOnInit(): void {
  }

}

test-component.component.html

<!-- 1. 屬性綁定 -->
<!-- 1.1 Attribute綁定 -->
<div [id]="'box'">屬性綁定常量</div>
<!-- 如果不加單引號(hào),Ng會(huì)將內(nèi)容當(dāng)作變量進(jìn)行解析 -->
<div [id]="name">屬性綁定變量</div>

<!-- 1.2 類綁定 -->
<!-- 渲染成類名為 h3-dom,等號(hào)右邊的結(jié)果會(huì)被轉(zhuǎn)化成 Boolean,為 true 則渲染 -->
<h3 [class.h3-dom]="h3Dom">hello H3</h3>
<h3 [class]="'h3-dom font-w string'">多類名綁定</h3>
<!-- 根據(jù)不同的變量綁定不同的class -->
<h3 [class]="{'h3-dom': true, 'title-dom': false}">類名條件渲染</h3>
<h3 [class]="['h3-dom', 'title-dom']">class數(shù)組渲染</h3>

<!-- 1.3 樣式綁定 -->
<h3 [style.width]="'300px'">單一樣式綁定</h3>
<!-- 帶單位的單一樣式綁定 -->
<h3 [style.width.px]="'300'">單一樣式綁定</h3>
<!-- 多重樣式綁定 -->
<h3 [style]="'background:red; color: #fff'">字符串形式多重樣式綁定</h3>
<h3 [style]="{'background': 'red', 'color': '#fff'}">對(duì)象形式多重樣式綁定</h3>
<!-- 使用 ngClass 綁定樣式 -->
<h3 [ngClass]="{'h3Dom': h3Dom}">ngClass綁定</h3>
<h3 [style]="{'background': 'red'}">ngStyle綁定, 也可以使用三元表達(dá)式進(jìn)行書寫</h3>

3.3 條件判斷

test-component.component.ts

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

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

  name:String = 'Alex'
  h3Dom:Boolean = true
  isShowMyDiv:Boolean = true
  constructor() { }

  ngOnInit(): void {
  }

}

test-component.component.html

<!-- 2. 條件判斷 -->
<div *ngIf="isShowMyDiv">條件判斷</div>
<!-- 解析后,它是直接影響元素的渲染,不是使用css隱藏 -->
<ng-template [ngIf]="isShowMyDiv">
  <div>條件判斷</div>
</ng-template>

<!-- if-else -->
<ng-container *ngIf="!isShowMyDiv; else elseTemplate">
  <div>if</div>
</ng-container>
<ng-template #elseTemplate>
  <div>else</div>
</ng-template>

3.4 循環(huán)語句

解析器會(huì)把 let color, let i 和 let odd翻譯成命名變量 color, i 和 odd
微語法解析器接受of,會(huì)將他的首字母大寫(Of), 然后加上屬性的指令名(ngFor)前綴, 最終生成的名字是 ngFor的輸入屬性(colors)
NgFor指令在列表上循環(huán),每個(gè)循環(huán)中都會(huì)設(shè)置和重置它自己的上下文對(duì)象上的屬性。這些屬性包括 index 和odd以及一個(gè)特殊的屬性名 implicit(隱式變量) Angular將let-color設(shè)置為此上下文中的implicit屬性的值, 它是由NgFor用當(dāng)前迭代中的colors初始化的
NgFor
test-component.component.ts

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

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

  name:String = 'Alex'
  h3Dom:Boolean = true
  isShowMyDiv:Boolean = true


  colors:Array<String> = ['red', 'blue', 'yellow', 'green']
  type:Boolean = true

  constructor() { }

  ngOnInit(): void {
  }

}

test-component.component.html

<!-- 3. 循環(huán)語句 -->
<!-- for循環(huán) -->
<div *ngFor="let color of colors let i=index let odd=odd">
  {{ odd }}
  {{ i }}
  {{ color }}
</div>
<!-- 解析后 -->
<ng-template ngFor let-color [ng-for]="colors" let-i="index" let-odd="odd">
  <div>
    {{ odd }}
    {{ i }}
    {{ color }}
  </div>
</ng-template>


<!-- switch 用于判斷變量的不同情況 -->
<span [ngSwitch]="type">
<p *ngSwitchCase="true">
type === true
</p>
<p *ngSwitchCase="false">
type === false
</p>
<p *ngSwitchDefault>
默認(rèn)顯示
</p>
</span>

3.5 事件綁定

** 事件綁定**
事件綁定語法由左側(cè)括號(hào)內(nèi)的目標(biāo)時(shí)間名和右側(cè)引號(hào)內(nèi)的模板語句組成。目標(biāo)事件名是 click,模板語法是 onSave()
** 模板變量**
模板變量可以實(shí)現(xiàn)在當(dāng)前模板的另一個(gè)部分使用這個(gè)數(shù)據(jù)。使用模板變量
test-component.component.ts

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

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

  onSave(event:Event) {
    console.log('點(diǎn)擊了按鈕', event)
  }

  inputChange(event:Event) {
    console.log('觸發(fā)了Input', event)
  }

  getUserName(v:string) {
    console.log(v)
  }

  constructor() { }

  ngOnInit(): void {
  }

}

test-component.component.html

<p>test-component works!</p>

<button (click)="onSave($event)">Save</button>

<input #userName type="text" (input)="inputChange($event)" name="userName">

<button (click)="getUserName(userName.value)">GetUserName</button>

3.6 數(shù)據(jù)雙向綁定ngModel

雙向綁定是應(yīng)用中的組件共享數(shù)據(jù)的一種方式,使用雙向綁定來偵聽事件并在父組件和子組件之間同步更新
ngModel指令只對(duì)表單元素有效,所以在使用之前需要導(dǎo)入 FormsModule 模塊

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { TestComponentComponent } from './test-component/test-component.component';

@NgModule({
  declarations: [
    AppComponent,
    TestComponentComponent
  ],
  // 申明組件需要用到的類
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

test-component.component.ts

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

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

  username:String = ''

  constructor() { }

  ngOnInit(): void {
  }
}

test-component.component.html

<p>test-component works!</p>

<div>
  Input: <input [(ngModel)]="username">
  <h1>You are Typing: {{ username }}</h1>
</div>

3.7 表單控件

使用表單控件有三個(gè)步驟

  1. 在應(yīng)用中注冊(cè)響應(yīng)式表單模塊,該模塊聲明了一些你要用在響應(yīng)式表單中的指令
  2. 生成一個(gè)新的 FormControl實(shí)例,并把它保存在組件中
  3. 在模板中注冊(cè)這個(gè) FormControl
    從 @angular/forms包中導(dǎo)入 ReactiveFormsModule, 并把它添加到你的 NgModule 的 imports 數(shù)組中
import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms'

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

 myForm:FormControl = new FormControl('')

 handleChangeName () {
   // 必須通過 setValue 去修改值
   this.myForm.setValue('黃小明')
 }

 constructor() { }

 ngOnInit(): void {
 }
}
<p>test-component works!</p>

<label>
  Name: <input type="text" [formControl]="myForm">
</label>

<div>
  value: {{ myForm.value }}
</div>

<button (click)="handleChangeName()" >ChangeName</button>

3.8 表單控件分組

表單中通常包含幾個(gè)相互管理的控件。響應(yīng)式表單提供了兩種把多個(gè)相關(guān)控件分組到同一個(gè)輸入表單中的方法
如果要將表單組添加到此組件中,請(qǐng)執(zhí)行以下步驟

  1. 創(chuàng)建一個(gè) FormGroup 實(shí)例
  2. 把這個(gè) FormGroup 模型關(guān)聯(lián)到視圖
  3. 保存表單數(shù)據(jù)
    創(chuàng)建一個(gè) FormGroup實(shí)例
    在組件類中創(chuàng)建一個(gè)名為 loginForm 的屬性, 并設(shè)置為 FormGroup 的一個(gè)新實(shí)例。要初始化這個(gè) FormGroup,需要為構(gòu)造函數(shù)提供一個(gè)由控件組成的對(duì)象,對(duì)象中的每個(gè)名字都要和表單控件的名字一一對(duì)應(yīng)
    test-component.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms'

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

  loginForm = new FormGroup({
    username: new FormControl(''),
    password: new FormControl('')
  })

  handleShowData() {
      console.log(this.loginForm.value)
  }

  constructor() { }

  ngOnInit(): void {
  }
}

test-component.component.html

<p>test-component works!</p>

<form [formGroup]="loginForm">
  <label>
    username: <input type="text" formControlName="username">
    password: <input type="password" formControlName="password">
  </label>
  <button (click)="handleShowData()">ShowData</button>
</form>

3.9 表單驗(yàn)證

表單元素添加 required 關(guān)鍵字表示必填,通過綁定ngModel的引用可以拿到當(dāng)前組件的信息,通過引用獲取驗(yàn)證的信息
test-component.component.ts

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

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

  formData = {
    name: '',
    password: ''
  }

  handleSubmit(obj:Object) {
    console.log(obj)
  }

  constructor() { }

  ngOnInit(): void {
  }
}

test-component.component.html

<p>test-component works!</p>

<form action="">
  name: <input required #nameInp="ngModel" type="text" [(ngModel)]="formData.name" name="userName" />
  <br>
  <!-- 驗(yàn)證是否通過 -->
  <span>表單驗(yàn)證結(jié)果: {{ nameInp.valid }}</span>
  <hr>
  password: <input required #pasInp="ngModel" type="text" [(ngModel)]="formData.password" name="password" />
  <br>
  <span>{{ pasInp.valid }}</span>
  <hr>
  <button (click)="handleSubmit(nameInp)">submit</button>
</form>

可以通過 ngModel 跟蹤修改狀態(tài)與有效性驗(yàn)證,它使用了三個(gè)CSS類來更新控件,用于反應(yīng)當(dāng)前狀態(tài)

狀態(tài) 為 true 時(shí)的類 為 false 時(shí)的類
控件已經(jīng)被訪問過 ng-touch ng-untouched ng-pristine
控件值時(shí)有效的 ng-valid ng-invalid

3.10 自定義表單驗(yàn)證

首先要引入幾個(gè)類
test-component.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'

@Component({
  selector: 'app-test-component',
  templateUrl: './test-component.component.html',
  styleUrls: ['./test-component.component.scss']
})
export class TestComponentComponent implements OnInit {
  // 構(gòu)造函數(shù)里注入 FormBuilder
  constructor(private formBuilder:FormBuilder) { }

  userName:String = ''
  password:String = ''
  phone:String = ''

  // 表單驗(yàn)證規(guī)則
  valiDateForm:FormGroup = this.formBuilder.group({
    userName: ['', [
      Validators.required, Validators.maxLength(18), Validators.minLength(6)
    ]],
    password: ['', [this.passwordVal]],
    // 同時(shí)使用內(nèi)置驗(yàn)證,也使用自定義驗(yàn)證
    phone: ['', [Validators.required, this.phoneVal]]
  })

  // 自定義驗(yàn)證
  phoneVal(phone:FormControl):Object {
    const value = phone.value || ''
    if(!value) return { msg: '請(qǐng)輸入手機(jī)號(hào)' }
    const valid = /[0-9]{11}/.test(value)
    return valid ? {} : { msg: '聯(lián)系電話必須是11為數(shù)字' }
  }

  // 自定義驗(yàn)證
  passwordVal(password:FormControl):Object {
    const value = password.value || ''
    const valid = value > 0
    return valid ? {} : {msg: '密碼至少把啦啦啦。。。'}
  }

  handleSubmit() {
    console.log(this.valiDateForm.get('userName'))
  }

  ngOnInit(): void {

  }
}

test-component.component.html

<p>test-component works!</p>

<form [formGroup]="valiDateForm">
  username: <input required type="text" formControlName="userName"/>
  <p>{{ valiDateForm.get('userName')?.errors?'驗(yàn)證失敗':''}}</p>
  password: <input required type="password" formControlName="password"/>
  phone: <input required type="number" formControlName="phone"/>
  <button (click)="handleSubmit()">提交</button>
</form>

3.11 管道

管道的作用是傳輸,不同的管道具有不同的作用。(其實(shí)就是數(shù)據(jù)處理)(其實(shí)就是Vue2中的Filter)

管道 功能
DatePipe 日期管道,格式化日期
JsonPipe 將輸入數(shù)據(jù)對(duì)象經(jīng)過JSON.stringfy()方法轉(zhuǎn)換后輸出的字符串
UpperCasePipe 將文本所有小寫字母轉(zhuǎn)換成大寫字母
LowerCasePipe 將文本所有大寫字母轉(zhuǎn)換成小寫字母
DecimalPipe 將數(shù)值按照特定的格式顯示文本
CurrentcyPipe 將數(shù)值進(jìn)行貨幣格式化處理
SlicePipe 將數(shù)組或者字符串裁剪成新字符串
PercentPipe 將數(shù)值轉(zhuǎn)百分比格式

pipe用法
{{ 輸入數(shù)據(jù) | 管道:管道參數(shù) }} (其中'|'是管道操作符)
鏈?zhǔn)焦艿?{{ 輸入數(shù)據(jù) | date | uppercase }}
管道流通方向自左向右,逐層執(zhí)行
創(chuàng)建自定義管道:使用腳手架命令:ng g p test

3.12 生命周期

鉤子方法 用途 時(shí)機(jī)
ngOnchanges() 當(dāng) Angular 設(shè)置或重新設(shè)置數(shù)據(jù)綁定的輸入屬性時(shí)響應(yīng)。 該方法接受當(dāng)前和上一屬性值的 SimpleChanges 對(duì)象。注意,這發(fā)生的非常頻繁,所以你在這里執(zhí)行的任何操作都會(huì)顯著影響性能。 在 ngOnInit() 之前以及所綁定的一個(gè)或多個(gè)輸入屬性的值發(fā)生變化時(shí)都會(huì)調(diào)用。注意,如果你的組件沒有輸入,或者你使用它時(shí)沒有提供任何輸入,那么框架就不會(huì)調(diào)用 ngOnChanges()。
ngOnInit() 在 Angular 第一次顯示數(shù)據(jù)綁定和設(shè)置指令/組件的輸入屬性之后,初始化指令/組件。 在第一輪 ngOnChanges() 完成之后調(diào)用,只調(diào)用一次。
ngDoCheck() 檢測(cè),并在發(fā)生 Angular 無法或不愿意自己檢測(cè)的變化時(shí)作出反應(yīng)。 緊跟在每次執(zhí)行變更檢測(cè)時(shí)的 ngOnChanges() 和 首次執(zhí)行變更檢測(cè)時(shí)的 ngOnInit() 后調(diào)用。
ngAfterContentInit() 當(dāng) Angular 把外部內(nèi)容投影進(jìn)組件視圖或指令所在的視圖之后調(diào)用。 第一次 ngDoCheck() 之后調(diào)用,只調(diào)用一次
ngAfterContentChecked() 每當(dāng) Angular 檢查完被投影到組件或指令中的內(nèi)容之后調(diào)用。 ngAfterContentInit() 和每次 ngDoCheck() 之后調(diào)用
ngAfterViewInit() 當(dāng) Angular 初始化完組件視圖及其子視圖或包含該指令的視圖之后調(diào)用。 第一次 ngAfterContentChecked() 之后調(diào)用,只調(diào)用一次。
ngAfterViewChecked() 每當(dāng) Angular 做完組件視圖和子視圖或包含該指令的視圖的變更檢測(cè)之后調(diào)用。 ngAfterViewInit() 和每次 ngAfterContentChecked() 之后調(diào)用。
ngOnDestroy() 每當(dāng) Angular 每次銷毀指令/組件之前調(diào)用并清掃。 在這兒反訂閱可觀察對(duì)象和分離事件處理器,以防內(nèi)存泄漏。 在 Angular 銷毀指令或組件之前立即調(diào)用。

在開發(fā)中比較常用的生命周期是
ngOnChanges()
ngOnInit()
ngOnDestroy()

3.13 組件交互

@Input
父組件通過 @Input 給子組件綁定屬性設(shè)置輸入類數(shù)據(jù)
父傳子類似Vue中的,父組件用冒號(hào)給子組件傳值
父組件 home.component.html

 <app-title [title]="title"></app-title>

子組件 title.component.ts

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

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

  constructor() { }

  @Input()
  title?:String

  // 一般開發(fā)中常用的生命周期
  ngOnChanges(): void {
  }

  ngOnInit(): void {
  }

  ngOnDestroy(): void {
  }
}

@Output
父組件給子組件傳遞一個(gè)事件,子組件通過@Output發(fā)射觸發(fā)事件
子傳父,類似Vue中,this.$emit()
父組件 home.component.html

<p>home works!</p>
<app-title (addList)="addListFun($event)"></app-title>
{{ list }}

父組件 home.component.ts

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

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

  constructor() { }

  list:Array<String> = ['1', '2']

  addListFun(str:String) {
    this.list?.push(str)
  }

  ngOnInit(): void {
  }

}

子組件 title.component.ts

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

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

  constructor() { }

  inputValue:String = '111'

  @Output() addList = new EventEmitter()

  pushList() {
    this.addList.emit(this.inputValue)
  }

  ngOnInit(): void {
    this.pushList()
  }
}

@ViewChild()
通過 @viewChild 獲取子組件實(shí)例, 獲取子組件數(shù)據(jù)
父組件 home.component.html

<p>home works!</p>
<app-title #myAppTitle (addList)="addListFun($event)"></app-title>
{{ list }}

父組件 home.component.ts

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

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

  constructor() { }

  list:Array<String> = ['1', '2']

  addListFun(str:String) {
    this.list?.push(str)
  }

  @ViewChild('myAppTitle') child:any

  ngOnInit(): void {
    setTimeout(() => {
      // 此處相當(dāng)于 Vue 中通過 refs 拿到了子組件的實(shí)例
      console.log(this.child)
    }, 1000);
  }
}

4. 服務(wù)與依賴注入

4.1 服務(wù)

angular中, 把從組件抽離出來的代碼叫服務(wù),服務(wù)的本質(zhì)是方法(函數(shù))
官方認(rèn)為組件不應(yīng)該直接獲取或保存數(shù)據(jù),它們應(yīng)該聚焦于展示數(shù)據(jù),而把數(shù)據(jù)訪問的職責(zé)委托給某個(gè)服務(wù)。而服務(wù)就起著數(shù)據(jù)訪問,邏輯處理的功能。把組件和服務(wù)區(qū)分開,以提高模塊性和復(fù)用性。通過把組件中的視圖有關(guān)的功能與其他類型的處理分離開,可以讓組件類更精簡、高效
可以使用如下命令創(chuàng)建一個(gè)服務(wù),通過 @Injectable() 裝飾器標(biāo)識(shí)服務(wù)

ng g s xxx

下面演示創(chuàng)建一個(gè) list 服務(wù)
list.service.ts

// 導(dǎo)入 Injectable 裝飾器
import { Injectable } from '@angular/core';

// 是哦那個(gè) Injectable 裝飾器聲明服務(wù)
@Injectable({
  // 作用域設(shè)定
  // root表示默認(rèn)注入,注入到 app.module.ts內(nèi)
  // 也可以寫 null,表示不設(shè)定區(qū)域
  // 還可以是某個(gè)模塊的名字(一般是懶加載模式)
  providedIn: 'root'
})
export class ListService {

  constructor() { }
}

4.2 依賴注入

創(chuàng)建一個(gè)服務(wù)

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

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

  constructor() { }

  // 注意該server是數(shù)據(jù)源,全局唯一
  myList:Array<String> = ['Angular', 'React', 'Vue']

  getList() {
    // 此處可以進(jìn)行異步的數(shù)據(jù)請(qǐng)求
    return this.myList
  }

  addList(str:String) {
    this.myList.push(str)
  }
}

在 app.module.ts 中引入服務(wù)

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { TestComponentComponent } from './test-component/test-component.component';
import { MyPipePipe } from './my-pipe.pipe';
import { HomeComponent } from './home/home.component';
import { TitleComponent } from './title/title.component';
// 引入服務(wù)
import { ListService } from './servers/list.service';

@NgModule({
  declarations: [
    AppComponent,
    TestComponentComponent,
    MyPipePipe,
    HomeComponent,
    TitleComponent
  ],
  // 申明組件需要用到的類
  imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule,
    FormsModule
  ],
  // 注冊(cè)服務(wù)
  providers: [ListService],
  bootstrap: [AppComponent]
})
export class AppModule { }

在組件中使用服務(wù)
home.component.ts

// 引入服務(wù)
import { ListService } from './../servers/list.service';
import { Component, OnInit} from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})

export class HomeComponent implements OnInit {

  constructor(private listService:ListService) { }

  list:Array<String> | undefined

  ngOnInit(): void {
    setTimeout(() => {
      this.list = this.listService.getList()
      console.log(this.list)
    }, 1000);
 }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容