參考上節的內容,我們按下面的步驟完成編輯功能前臺的初始化操作:
1. 組件C層初始化。
2. 新建組件V層初始化。
3. 將組件添加到對應的模塊中。
4. 建立路由與組件進行關聯。
# 初始化
## C層
和前面的增加數據組件的命名方式相似,我們將其命名為:teacher-edit.component.ts
```js
import {Component, OnInit} from '@angular/core';
@Component({
templateUrl: './teacher-edit.component.html'
})
export class TeacherEditComponent implements OnInit {
ngOnInit(): void {
}
}
```
## V層
teacher-edit.component.html
```html
teacher edit!
```
添加新文件后目錄結構如下:
```
.
├── app-routing.module.ts
├── app.component.html
├── app.component.sass
├── app.component.spec.ts
├── app.component.ts
├── app.module.ts
├── teacher-add.component.html
├── teacher-add.component.ts
├── teacher-edit.component.html
└── teacher-edit.component.ts
```
## 組件添加到模塊
app.module.ts
```js
import {TeacherEditComponent} from './teacher-edit.component'; ?
@NgModule({
declarations: [
AppComponent,
TeacherAddComponent,
TeacherEditComponent ?
],
```
> 使用“?”來標記出文件變動的位置,同時說明該知識點前面的章節已經涉及過,此處不再重復講解。
## 路由
app-routing.module.ts
```js
import {NgModule} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';
import {TeacherAddComponent} from './teacher-add.component';
import {TeacherEditComponent} from './teacher-edit.component'; ?
const routes: Routes = [
{
path: 'add',
component: TeacherAddComponent
},
{ ?
path: 'edit', ?
component: TeacherEditComponent ?
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
```
* ? 在數組中添加新對象
## 測試

# 獲取URL中的參數
在編輯數據前,我們需要通過`URL`來獲取用戶當前需要編輯教師的ID。比如用戶需要編輯ID為1的教師,則`URL`應該是[http://localhost:4200/edit/1](http://localhost:4200/edit/1)或[http://localhost:4200/edit?id=1](http://localhost:4200/edit?id=1)或者更新新穎的[http://localhost:4200/edit;d=1](http://localhost:4200/edit;d=1)形式。
## PATH模式
[http://localhost:4200/edit/1](http://localhost:4200/edit/1)是以后我們在項目中使用的最多,也是最常見的一種,定義路由及獲取路由參數的方法相對較簡單容易理解,我們又常稱這種方法為`PATH模式`。
AppRoutingModule
```js
const routes: Routes = [
{
path: 'add',
component: TeacherAddComponent
},
{
path: 'edit/:id', ?
component: TeacherEditComponent
}
];
```
* ? 使用具體的id值來替換`:id`,即達到傳入參數的目的。比如`edit/1`表示傳入的`id`值為1
路由定義完成后,我們[http://localhost:4200/edit/1](http://localhost:4200/edit/1),并嘗試在`TeacherEditComponent`中獲取該`路由參數`的值。
### 獲取路由參數的值
teacher-edit.component.ts
```js
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router'; ?
@Component({
templateUrl: './teacher-edit.component.html'
})
export class TeacherEditComponent implements OnInit {
constructor(private route: ActivatedRoute ?) {
}
ngOnInit(): void {
const id = this.route.snapshot.paramMap.get('id'); ?
console.log(id); ?
}
}
```
* ? 調用路由對象的`快照`屬性的`參數Map`屬性的`get()`方法,傳入要獲取參數的關鍵字`id`來獲取參數的值
### 測試

## GET模式
在很多常的項目中,使用最常用的`get`方式在參數中使用`?key1=value1*key2=value2`的方法來進行傳值仍然是首選。雖然我們并不推薦這么做,但某些特殊的情況下我們的確也需要借助該方法來傳值。在`GET模式`,訪問地址為:[http://localhost:4200/edit?id=1](http://localhost:4200/edit?id=1)。
### 修改路由
app-routing.module.ts
```js
{
path: 'edit', ?
component: TeacherEditComponent
}
```
* ? 由`edit/:id`修正為`edit`。
### 獲取GET參數的值
teacher-edit.component.ts
```js
ngOnInit(): void {
const id = this.route.snapshot.queryParamMap.get('id'); ?
console.log(id);
}
```
* ? 由this.route.snapshot.`paramMap`.get('id');修正為this.route.snapshot.`queryParamMap`.get('id');
### 測試
訪問:[http://localhost:4200/edit?id=1](http://localhost:4200/edit?id=1)

## 矩陣URL
另有一種URL寫法是[http://localhost:4200/edit;d=1](http://localhost:4200/edit;id=1),它被稱為`Matrix URL 矩陣URL`,寫法首次提出是在[1996 提案](http://www.w3.org/DesignIssues/MatrixURIs.html)中,提出者是 Web 的奠基人:Tim Berners-Lee。在angular中,獲取該參數值的方法同`PATH模式`相同。
TeacherEditComponent
```js
ngOnInit(): void {
const id = this.route.snapshot.paramMap.get('id'); ?
console.log(id);
}
```
### 測試

# 本節作業
把路由恢復為`PATH`模式,并在V層中直接顯示獲取到的`id`的值。
**作業完成后請繼續學習**
# 定義請求接口規范
現在,我們可以為后臺定義一個接口規范。然后將此規范發送給后臺成員,最終待后臺開發完成后完成對接了。在進行某個特定的數據請求時,我們會這樣定義:方法`GET`、地址`資源名\資源ID`,比如此時我們需要定的接口地址為:方法:`GET`、地址:`Teacher\<id>`。
> `Teacher\<id>`表示,此地址需要被特定的`id`值覆蓋且`id`為必選項,比如`id = 1`則此地址為:`Teacher\1`。
## C層完成對接
由URL中獲取到了教師的ID,并且剛剛也定義了請求的接口規范,此時我們便可以參考前面的小節完成模擬的數據請求了。
TeacherEditComponent
```js
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {HttpClient} from '@angular/common/http'; ①
@Component({
templateUrl: './teacher-edit.component.html'
})
export class TeacherEditComponent implements OnInit {
public teacher: any;
constructor(private route: ActivatedRoute, private httpClient: HttpClient ②) {
}
ngOnInit(): void {
const id = this.route.snapshot.paramMap.get('id');
const url = 'http://localhost:8080/Teacher/' + id;
this.httpClient.get(url) ③
.subscribe((data) => {
this.teacher = data;
}, () => {
console.log(`請求 ${url} 時發生錯誤`); ?
});
}
}
```
* ? 拼接請求地址
* ? 注意此時``console.log(`直接引用變量的字符串`)``中使用的是 `` ` `` (ESC下邊、數字1左邊、TAB上邊那個以前或許沒用過的按鍵),而不是 ` ' ` 。``console.log(`請求 ${url} 時發生錯誤`)`` 等價于`console.log('請求 ' + url + ' 時發生錯誤');`
為了提升開發的效率、降低開發的難度,此時在V層直接打印這個教師。
teacher-edit.component.html
```html
<pre>{{teacher | json}}</pre>
```
## 測試

> 在沒有后臺的情況下,注定會發生請求錯語。
## 總結
1. **paramMap**獲取PATH模式下及矩陣模式下的傳值,**queryParamMap**獲取GET模式下的傳值。
2. PATH模式下,需要在路由中定義參數名稱;矩陣模式下及GET模式下,**不**需要在路由中定義參數名稱。
# 參考文檔
| 名稱 | 鏈接 | 預計學習時長(分) |
| --- | --- | --- |
| *Snapshot*(快照):當不需要 Observable 時的替代品 | [https://www.angular.cn/guide/router#snapshot-the-no-observable-alternative](https://www.angular.cn/guide/router#snapshot-the-no-observable-alternative) | 2 |
| 路由參數 | [https://www.angular.cn/guide/router#route-parameters](https://www.angular.cn/guide/router#route-parameters) | 3 |
| 源碼地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.4.1](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.4.1) | - |
- 序言
- 第一章:Hello World
- 第一節:Angular準備工作
- 1 Node.js
- 2 npm
- 3 WebStorm
- 第二節:Hello Angular
- 第三節:Spring Boot準備工作
- 1 JDK
- 2 MAVEN
- 3 IDEA
- 第四節:Hello Spring Boot
- 1 Spring Initializr
- 2 Hello Spring Boot!
- 3 maven國內源配置
- 4 package與import
- 第五節:Hello Spring Boot + Angular
- 1 依賴注入【前】
- 2 HttpClient獲取數據【前】
- 3 數據綁定【前】
- 4 回調函數【選學】
- 第二章 教師管理
- 第一節 數據庫初始化
- 第二節 CRUD之R查數據
- 1 原型初始化【前】
- 2 連接數據庫【后】
- 3 使用JDBC讀取數據【后】
- 4 前后臺對接
- 5 ng-if【前】
- 6 日期管道【前】
- 第三節 CRUD之C增數據
- 1 新建組件并映射路由【前】
- 2 模板驅動表單【前】
- 3 httpClient post請求【前】
- 4 保存數據【后】
- 5 組件間調用【前】
- 第四節 CRUD之U改數據
- 1 路由參數【前】
- 2 請求映射【后】
- 3 前后臺對接【前】
- 4 更新數據【前】
- 5 更新某個教師【后】
- 6 路由器鏈接【前】
- 7 觀察者模式【前】
- 第五節 CRUD之D刪數據
- 1 綁定到用戶輸入事件【前】
- 2 刪除某個教師【后】
- 第六節 代碼重構
- 1 文件夾化【前】
- 2 優化交互體驗【前】
- 3 相對與絕對地址【前】
- 第三章 班級管理
- 第一節 JPA初始化數據表
- 第二節 班級列表
- 1 新建模塊【前】
- 2 初識單元測試【前】
- 3 初始化原型【前】
- 4 面向對象【前】
- 5 測試HTTP請求【前】
- 6 測試INPUT【前】
- 7 測試BUTTON【前】
- 8 @RequestParam【后】
- 9 Repository【后】
- 10 前后臺對接【前】
- 第三節 新增班級
- 1 初始化【前】
- 2 響應式表單【前】
- 3 測試POST請求【前】
- 4 JPA插入數據【后】
- 5 單元測試【后】
- 6 惰性加載【前】
- 7 對接【前】
- 第四節 編輯班級
- 1 FormGroup【前】
- 2 x、[x]、{{x}}與(x)【前】
- 3 模擬路由服務【前】
- 4 測試間諜spy【前】
- 5 使用JPA更新數據【后】
- 6 分層開發【后】
- 7 前后臺對接
- 8 深入imports【前】
- 9 深入exports【前】
- 第五節 選擇教師組件
- 1 初始化【前】
- 2 動態數據綁定【前】
- 3 初識泛型
- 4 @Output()【前】
- 5 @Input()【前】
- 6 再識單元測試【前】
- 7 其它問題
- 第六節 刪除班級
- 1 TDD【前】
- 2 TDD【后】
- 3 前后臺對接
- 第四章 學生管理
- 第一節 引入Bootstrap【前】
- 第二節 NAV導航組件【前】
- 1 初始化
- 2 Bootstrap格式化
- 3 RouterLinkActive
- 第三節 footer組件【前】
- 第四節 歡迎界面【前】
- 第五節 新增學生
- 1 初始化【前】
- 2 選擇班級組件【前】
- 3 復用選擇組件【前】
- 4 完善功能【前】
- 5 MVC【前】
- 6 非NULL校驗【后】
- 7 唯一性校驗【后】
- 8 @PrePersist【后】
- 9 CM層開發【后】
- 10 集成測試
- 第六節 學生列表
- 1 分頁【后】
- 2 HashMap與LinkedHashMap
- 3 初識綜合查詢【后】
- 4 綜合查詢進階【后】
- 5 小試綜合查詢【后】
- 6 初始化【前】
- 7 M層【前】
- 8 單元測試與分頁【前】
- 9 單選與多選【前】
- 10 集成測試
- 第七節 編輯學生
- 1 初始化【前】
- 2 嵌套組件測試【前】
- 3 功能開發【前】
- 4 JsonPath【后】
- 5 spyOn【后】
- 6 集成測試
- 7 @Input 異步傳值【前】
- 8 值傳遞與引入傳遞
- 9 @PreUpdate【后】
- 10 表單驗證【前】
- 第八節 刪除學生
- 1 CSS選擇器【前】
- 2 confirm【前】
- 3 功能開發與測試【后】
- 4 集成測試
- 5 定制提示框【前】
- 6 引入圖標庫【前】
- 第九節 集成測試
- 第五章 登錄與注銷
- 第一節:普通登錄
- 1 原型【前】
- 2 功能設計【前】
- 3 功能設計【后】
- 4 應用登錄組件【前】
- 5 注銷【前】
- 6 保留登錄狀態【前】
- 第二節:你是誰
- 1 過濾器【后】
- 2 令牌機制【后】
- 3 裝飾器模式【后】
- 4 攔截器【前】
- 5 RxJS操作符【前】
- 6 用戶登錄與注銷【后】
- 7 個人中心【前】
- 8 攔截器【后】
- 9 集成測試
- 10 單例模式
- 第六章 課程管理
- 第一節 新增課程
- 1 初始化【前】
- 2 嵌套組件測試【前】
- 3 async管道【前】
- 4 優雅的測試【前】
- 5 功能開發【前】
- 6 實體監聽器【后】
- 7 @ManyToMany【后】
- 8 集成測試【前】
- 9 異步驗證器【前】
- 10 詳解CORS【前】
- 第二節 課程列表
- 第三節 果斷
- 1 初始化【前】
- 2 分頁組件【前】
- 2 分頁組件【前】
- 3 綜合查詢【前】
- 4 綜合查詢【后】
- 4 綜合查詢【后】
- 第節 班級列表
- 第節 教師列表
- 第節 編輯課程
- TODO返回機制【前】
- 4 彈出框組件【前】
- 5 多路由出口【前】
- 第節 刪除課程
- 第七章 權限管理
- 第一節 AOP
- 總結
- 開發規范
- 備用