บทความนี้จะให้ความเข้าใจเชิงลึกเกี่ยวกับ NgRx ผู้จัดการสถานะของ Angular และแนะนำวิธีใช้ NgRx ฉันหวังว่ามันจะเป็นประโยชน์กับคุณ!
NgRx เป็นโซลูชันสถาปัตยกรรม Redux สำหรับการจัดการสถานะส่วนกลางในแอปพลิเคชันเชิงมุม [บทช่วยสอนที่เกี่ยวข้องที่แนะนำ: "บทช่วยสอนเชิงมุม"]
@ngrx/store: โมดูลการจัดการสถานะทั่วโลก
@ngrx/effects: การจัดการผลข้างเคียง
@ngrx/store-devtools: เครื่องมือแก้ไขข้อบกพร่องของเบราว์เซอร์จำเป็นต้องพึ่งพา Redux Devtools Extension
@ngrx/schematics: เครื่องมือบรรทัดคำสั่งเพื่อสร้างไฟล์ NgRx อย่างรวดเร็ว
@ngrx/entity: ปรับปรุงประสิทธิภาพของนักพัฒนาในการดำเนินงานข้อมูลใน REDUCER
@ngrx/router-store: ประสานสถานะเส้นทางกับร้านค้าทั่วโลก
1. ดาวน์โหลด NgRx
npm install @ngrx/store @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store-devtools @ngrx/schematics
2. กำหนดค่า NgRx CLI
ng config cli.defaultCollection @ngrx/schematics
// เชิงมุม json "คลิ": { "defaultCollection": "@ngrx/schematics" -
3. สร้างร้านค้า
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4. สร้างการดำเนินการ
ng g action store/actions/counter --skipTests
นำเข้า { createAction } จาก "@ngrx/store" ส่งออกส่วนเพิ่ม const = createAction ("ส่วนเพิ่ม") ส่งออก const ลดลง = createAction ("ลดลง")
5. สร้างตัวลด
ng g reducer store/reducers/counter --skipTests --reducers=../index.ts
นำเข้า { createReducer, บน } จาก "@ngrx/store" นำเข้า { ลดลง, เพิ่มขึ้น } จาก "../actions/counter.actions" ส่งออก const counterFeatureKey = "ตัวนับ" สถานะอินเทอร์เฟซการส่งออก { นับ: จำนวน - ส่งออก const InitialState: รัฐ = { นับ: 0 - ส่งออกตัวลด const = createReducer ( รัฐเริ่มต้น, บน (การเพิ่มขึ้น สถานะ => ({ นับ: state.count + 1 })) บน (การลดลง สถานะ => ({ นับ: state.count - 1 })) -
6. สร้างตัวเลือก
ng g selector store/selectors/counter --skipTests
นำเข้า { createFeatureSelector, createSelector } จาก "@ngrx/store" นำเข้า { counterFeatureKey, State } จาก "../reducers/counter.reducer" นำเข้า { AppState } จาก ".." ส่งออก const selectCounter = createFeatureSelector <AppState, State> (counterFeatureKey) ส่งออก const selectCount = createSelector (selectCounter, state => state.count)
7. คลาสส่วนประกอบทริกเกอร์การดำเนินการและรับสถานะ
นำเข้า { เลือก ร้านค้า } จาก "@ngrx/store" นำเข้า { สังเกตได้ } จาก "rxjs" นำเข้า { AppState } จาก "./store" นำเข้า { การลดลง การเพิ่มขึ้น } จาก "./store/actions/counter.actions" นำเข้า { selectCount } จาก "./store/selectors/counter.selectors" ส่งออกคลาส AppComponent { นับ: สังเกตได้<number> ตัวสร้าง (ร้านค้าส่วนตัว: ร้านค้า <AppState>) { this.count = this.store.pipe (เลือก (selectCount)) - เพิ่มขึ้น() { this.store.dispatch (เพิ่มขึ้น ()) - ลดลง() { this.store.dispatch (ลดลง ()) - -
8. สถานะการแสดงเทมเพลตส่วนประกอบ
<ปุ่ม (คลิก)="ส่วนเพิ่ม()">+</ปุ่ม> <span>{{ นับ |. async }}</span> <ปุ่ม (คลิก)="ลดค่า()">-</ปุ่ม>
1. ใช้การจัดส่งในส่วนประกอบเพื่อส่งพารามิเตอร์เมื่อทริกเกอร์การดำเนินการ และในที่สุดพารามิเตอร์จะถูกวางในออบเจ็กต์การดำเนินการ
this.store.dispatch (เพิ่มขึ้น ({ จำนวน: 5 }))
2. เมื่อสร้างฟังก์ชัน Action Creator ให้รับพารามิเตอร์และระบุประเภทพารามิเตอร์
นำเข้า { createAction, อุปกรณ์ประกอบฉาก } จาก "@ngrx/store" ส่งออกส่วนเพิ่ม const = createAction ("เพิ่มขึ้น", อุปกรณ์ประกอบฉาก <{ นับ: หมายเลข }> ())
ส่งออกประกาศฟังก์ชั่นอุปกรณ์ประกอบฉาก <P ขยายวัตถุ> (): อุปกรณ์ประกอบฉาก <P>;
3. รับพารามิเตอร์ผ่านอ็อบเจ็กต์ Action ในตัวลด
ส่งออกตัวลด const = createReducer ( รัฐเริ่มต้น, บน (การเพิ่มขึ้น (สถานะการกระทำ) => ({ นับ: state.count + action.count })) -
metaReducer เป็นจุดเชื่อมระหว่าง Action -> ลดขนาด ช่วยให้นักพัฒนาสามารถประมวลผลการกระทำล่วงหน้า (เรียกว่าก่อนการเรียกใช้ฟังก์ชันลดปกติ)
ฟังก์ชั่นดีบัก (ตัวลด: ActionReducer <ใด ๆ >): ActionReducer <ใด ๆ> { ฟังก์ชั่นส่งคืน (สถานะ, การกระทำ) { ตัวลดผลตอบแทน (สถานะ, การกระทำ) - - ส่งออก const metaReducers: MetaReducer<AppState>[] = !environment.production ?[แก้ไขจุดบกพร่อง] -
ข้อกำหนด: เพิ่มปุ่มลงในเพจ หลังจากคลิกปุ่มแล้ว ให้หน่วงเวลาหนึ่งวินาทีเพื่อให้ค่าเพิ่มขึ้น
1. เพิ่มปุ่มสำหรับการเพิ่มค่าแบบอะซิงโครนัสในเทมเพลตส่วนประกอบ หลังจากคลิกปุ่มแล้ว เมธอด increment_async
จะถูกดำเนินการ
<button (click)="increat_async()">async</button>
2. เพิ่มเมธอด increment_async
ให้กับคลาสส่วนประกอบและทริกเกอร์การดำเนินการเพื่อดำเนินการแบบอะซิงโครนัสในเมธอด
increase_async() { this.store.dispatch (increase_async ()) -
3. เพิ่มการดำเนินการเพื่อดำเนินการแบบอะซิงโครนัสในไฟล์การดำเนินการ
ส่งออก const increat_async = createAction("increat_async")
4. สร้างเอฟเฟกต์ รับแอคชั่นและแสดงผลข้างเคียง และกระตุ้นแอคชั่นต่อไป
ng g effect store/effects/counter --root --module app.module.ts --skipTests
ฟังก์ชัน Effect จัดทำโดยโมดูล @ngrx/effects ดังนั้นจึงจำเป็นต้องนำเข้าการขึ้นต่อกันของโมดูลที่เกี่ยวข้องในโมดูลรูท
นำเข้า { ฉีดได้ } จาก "@เชิงมุม/แกน" นำเข้า { Actions, createEffect, ofType } จาก "@ngrx/effects" นำเข้า { การเพิ่มขึ้น, increat_async } จาก "../actions/counter.actions" นำเข้า { mergeMap, map } จาก "rxjs/operators" นำเข้า { ตัวจับเวลา } จาก "rxjs" // createEffect // ใช้เพื่อสร้างเอฟเฟกต์, เอฟเฟกต์ใช้เพื่อแสดงผลข้างเคียง // ส่งฟังก์ชันการโทรกลับเมื่อเรียกใช้เมธอด และส่งคืนวัตถุที่สังเกตได้ในฟังก์ชันการโทรกลับ วัตถุ Action ที่จะทริกเกอร์หลังจากดำเนินการผลข้างเคียง // ค่าที่ส่งคืนของฟังก์ชันการโทรกลับจะยังคงถูกส่งคืนภายใน createEffect และค่าที่ส่งคืนสุดท้ายจะถูกเก็บไว้ในคุณสมบัติของคลาส Effect // หลังจากสร้างอินสแตนซ์ของคลาส Effect แล้ว NgRx จะสมัครสมาชิกคุณสมบัติของคลาส Effect เมื่อผลข้างเคียงเสร็จสิ้น มันจะได้รับวัตถุ Action ที่จะทริกเกอร์ และกระตุ้นให้เกิดการกระทำ //การกระทำ // เมื่อส่วนประกอบทริกเกอร์การดำเนินการ เอฟเฟกต์จะต้องได้รับการดำเนินการผ่านบริการการดำเนินการ ดังนั้นในคลาสเอฟเฟกต์ อ็อบเจ็กต์อินสแตนซ์ของคลาสบริการการดำเนินการจะถูกฉีดเข้าไปในคลาสเอฟเฟกต์ผ่านพารามิเตอร์ตัวสร้าง object ของคลาสบริการ Actions นั้นสามารถสังเกตได้ Object เมื่อ Action ถูกทริกเกอร์ ตัว Action เองก็จะถูกปล่อยออกมาเป็น data stream // ofType // กรองวัตถุ Action เป้าหมาย // พารามิเตอร์คือฟังก์ชัน Action Creator ของ Action เป้าหมาย // หากไม่ได้กรองออบเจ็กต์ Action เป้าหมาย สตรีมข้อมูลจะไม่ถูกส่งต่อไปในครั้งนี้ // หากออบเจ็กต์ Action เป้าหมายถูกกรองออก ออบเจ็กต์ Action จะถูกส่งต่อไปเป็นสตรีมข้อมูล @Injectable() ส่งออกคลาส CounterEffects { ตัวสร้าง (การกระทำส่วนตัว: การกระทำ) { // this.loadCount.subscribe (console.log) - loadCount = createEffect(() => { ส่งคืน this.actions.pipe( ofType(increase_async) mergeMap(() => ตัวจับเวลา (1000).pipe(map(() => การเพิ่มขึ้น ({ จำนวน: 10 })))) - - -
1. ภาพรวม
เอนทิตีถูกแปลเป็นเอนทิตี และเอนทิตีคือชิ้นส่วนของข้อมูลในคอลเลกชัน
NgRx จัดเตรียมออบเจ็กต์อะแดปเตอร์เอนทิตี ภายใต้ออบเจ็กต์อะแดปเตอร์เอนทิตี มีการจัดเตรียมวิธีการต่างๆ สำหรับเอนทิตีการปฏิบัติงานในคอลเลกชัน
2. แกนกลาง
1. EntityState: อินเทอร์เฟซประเภทเอนทิตี
- - รหัส: [1, 2], เอนทิตี: { 1: { id: 1, หัวเรื่อง: "สวัสดีเชิงมุม" }, 2: { id: 2 ชื่อ: "สวัสดี NgRx" } - - - สถานะอินเทอร์เฟซการส่งออกขยาย EntityState<Todo> {}
2. createEntityAdapter: สร้างวัตถุอะแดปเตอร์เอนทิตี
3. EntityAdapter: อินเทอร์เฟซประเภทวัตถุอะแดปเตอร์เอนทิตี
ส่งออกอะแดปเตอร์ const: EntityAdapter<Todo> = createEntityAdapter<Todo>() // รับสถานะเริ่มต้น คุณสามารถส่งผ่านพารามิเตอร์วัตถุได้หรือไม่ // {ids: [], เอนทิตี: {}} ส่งออก const InitialState: State = adapter.getInitialState()
3. วิธีการอินสแตนซ์
https://ngrx.io/guide/entity/adapter#adapter-collection-methods
4. ตัวเลือก
// selectTotal รับจำนวนรายการข้อมูล // selectAll รับข้อมูลทั้งหมดและนำเสนอในรูปแบบของอาร์เรย์ // selectEntities รับการรวบรวมเอนทิตีและนำเสนอในรูปแบบของพจนานุกรม // selectIds รับการรวบรวม id และนำเสนอ ในรูปแบบของอาร์เรย์ const { selectIds, selectEntities, selectAll, selectTotal } = adapter .getSelectors();
ส่งออก const selectTodo = createFeatureSelector <AppState, State> (todoFeatureKey) ส่งออก const selectTodos = createSelector (selectTodo, เลือกทั้งหมด)
1. ประสานสถานะเส้นทาง
1) แนะนำโมดูล
นำเข้า { StoreRouterConnectingModule } จาก "@ngrx/router-store" @NgModule({ นำเข้า: [ ร้านค้าRouterConnectingModule.forRoot() - - ส่งออกคลาส AppModule {}
2) รวมสถานะเส้นทางเข้ากับ Store
นำเข้า * เป็น fromRouter จาก "@ngrx/router-store" ส่งออกอินเทอร์เฟซ AppState { เราเตอร์: fromRouter.RouterReducerState - ส่งออกตัวลด const: ActionReducerMap<AppState> = { เราเตอร์: fromRouter.routerReducer -
2. สร้างตัวเลือกเพื่อรับสถานะเส้นทาง
//router.selectors.ts นำเข้า { createFeatureSelector } จาก "@ngrx/store" นำเข้า { AppState } จาก ".." นำเข้า { RouterReducerState, getSelectors } จาก "@ngrx/router-store" const selectRouter = createFeatureSelector<AppState, RouterReducerState>( "เราเตอร์" - ส่งออก const { // รับข้อมูลที่เกี่ยวข้องกับเส้นทางปัจจุบัน (พารามิเตอร์เส้นทาง การกำหนดค่าเส้นทาง ฯลฯ) เลือกเส้นทางปัจจุบัน, // รับเนื้อหาหลังหมายเลข # ในแถบที่อยู่ selectFragment // รับพารามิเตอร์การสืบค้นการกำหนดเส้นทาง selectQueryParams // รับพารามิเตอร์การสืบค้นเฉพาะ selectQueryParam('name') เลือกแบบสอบถามพารามิเตอร์, // รับพารามิเตอร์การกำหนดเส้นทางแบบไดนามิก selectRouteParams // รับพารามิเตอร์การกำหนดเส้นทางแบบไดนามิกเฉพาะ selectRouteParam('name') เลือกเส้นทางพารามิเตอร์, // รับข้อมูลเส้นทางที่กำหนดเอง selectRouteData // รับที่อยู่การเข้าถึงที่แท้จริงของเส้นทาง selectUrl } = getSelectors (เลือกเราเตอร์)
// home.component.ts นำเข้า { เลือก ร้านค้า } จาก "@ngrx/store" นำเข้า {AppState} จาก "src/app/store" นำเข้า { selectQueryParams } จาก "src/app/store/selectors/router.selectors" ส่งออกคลาส AboutComponent { ตัวสร้าง (ร้านค้าส่วนตัว: ร้านค้า <AppState>) { this.store.pipe (เลือก (selectQueryParams)). สมัครสมาชิก (console.log) - -