4-1.Angular 入門教學 - Service與依賴注入基本概念和用法

Angular 入門教學

影片講解


一個小型的系統已經完成了

所以可以開始進一步優化程式部份了

那方法就是這章節要介紹的service

那service的基本功用,就是將你程式分割提取出去

那為什麼要進行程式上的分割呢?

比較常見的原因有以下三種

  1. 共用性:就是有兩個地方會用到相同的程式,那我們就會把它寫成一個service。
  2. 單一職責:這個service只負責同一類的事情,這樣會方便後續維護。
  3. 商業邏輯:把商業邏輯部分寫成一個service,也是可能利於後續的維護。

接下來的影片,會分別進行示範

這篇就先講解service基本的用法

首先,我們可以下一個指令,快速產生一個service的基本架構

ng g s example

接著就會在該目錄產生兩個檔案

那.spec的部分,我這個課程不會教到,而你以後也可能不會用到,所以我們可以到angular.json改設定,讓之後不會產生spec檔

找到schematics部分,在下方加上@schematics/angular:service,如下

"schematics": {
  "@schematics/angular:component": {
    "style": "scss"
  },
  "@schematics/angular:service": {
    "skipTests": true
  }
},

skipTests:true後,下次用指令產生service就不會有spec檔出現

接著我們簡單在剛產生的service寫個小程式

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

@Injectable({
  providedIn: 'root'
})
export class ExampleService {
  num = 0;

  constructor() { }

  add() {
    this.num++;
  }

}

裡面就一個變數跟方法,按下去後會加1

之後我們回到我們要使用的Component中,這邊我先增加兩個Component

至於Component的基本概念,下一章節就會介紹,這邊先看著就好

如上圖有a1跟a2的Component,接著來到app.component.html加入a1跟a2

app.component.html

<app-a1></app-a1>
<app-a2></app-a2>

如此在瀏覽器上面就會看到a1跟a2的內容

接著我們就要在a1跟a2中使用剛剛創建的service

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


  //這邊進行service的宣告
  constructor(private exampleService:ExampleService) { }

  ngOnInit(): void {
  }

}

在constructor中進行以上的宣告後,就能夠使用

接著我們增加一個變數跟方法

export class A1Component implements OnInit {
  get num() {
    return this.exampleService.num;
  }

  constructor(private exampleService: ExampleService) { }

  ngOnInit(): void {
  }

  add() {
    this.exampleService.add();
  }

}

變數是讀取ExampleService中的num變數,而add方法則是呼叫ExampleService中的add方法

接下來我們再到a1.component.html中放上對應要的東西,同時也在a2做一樣的事

<p>a1 works!</p>
{{num}}
<br>
<button (click)="add()">加一</button>

最後完成畫面如下

這時我們試著點擊"加一"看看會有什麼效果

可以看到a1跟a2的num是同步增加的,這代表了一件事情,我們這一個service是共用的

回到我們的example.service.ts,可以看到上面有一段這個

@Injectable({
  providedIn: 'root'
})

其中providedIn: ‘root’代表是幫我們providers到根模組

如果我們那掉這行試試看,會發現程式出現錯誤了

這個錯誤的意思是說,service沒有provider,所以無法使用

那早期其實沒有providedIn: ‘root’功能,所以我們會自行到app.module.ts註冊

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

import { AppComponent } from './app.component';
import { A1Component } from './a1/a1.component';
import { A2Component } from './a2/a2.component';
import { ExampleService } from './example.service';

@NgModule({
  declarations: [
    AppComponent,
    A1Component,
    A2Component
  ],
  imports: [
    BrowserModule
  ],
  //這邊進行註冊
  providers: [ExampleService],
  bootstrap: [AppComponent]
})
export class AppModule { }

此時存檔後,就會發現程式又正常運作了,而運作情況根剛剛是一樣的

那以上的兩種provider方式,會讓service是一個共用的狀態

不過其實我們可以分別provider到各自的Component中,如下

@Component({
  selector: 'app-a1',
  templateUrl: './a1.component.html',
  styleUrls: ['./a1.component.scss'],
  //這邊註冊
  providers: [ExampleService]
})
export class A1Component implements OnInit {
  get num() {
    return this.exampleService.num;
  }

  constructor(private exampleService: ExampleService) { }

  ngOnInit(): void {
  }

  add() {
    this.exampleService.add();
  }

}

此時我們再來看看效果

這時會發現我們的service中的num變數,已經沒有共用了,而是分別獨立的個體

那這個就是service基本的概念,跟不同依賴注入的效果

利用這種不同的注入方式,就可以依實際情況靈活的調用service

不過通常只有少部分會有獨立運作的需求,所以預設上現在都直接先註冊到root

好~~~光看介紹一定很難理解到底實際上的用處

所以我下一個影片馬上就會用todo範例實際操作service的用法

想看更多廢話,可以看影片~~~




Copyright © 凱哥寫程式 2022 | Powered by TalllKai ❤