? ?? angular? ?? ??? NgRx? ?? ???? ??? ????, NgRx ???? ???? ?? ?? ??? ??? ??? ????!
NgRx? Angular ??????? ?? ?? ??? ?? Redux ???? ??????. [?? ???? ????: "angular tutorial"]
@ngrx/store: ?? ?? ?? ??
@ngrx/events: ??? ??
@ngrx/store-devtools : ???? ??? ??? Redux Devtools Extension
@ngrx/schematics? ???? ?: NgRx ??? ??? ???? ??? ??
@ngrx/entity: Reducer?? ???? ???? ???? ??? ??
@ngrx/router-store: ??? ??? ?? Store
?? ??
1? ??????. NgRx
npm install @ngrx/store @ngrx/efficent @ngrx/entity @ ngrx/router-store @ngrx/store-devtools @ngrx/schematics
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
// angular.json "cli": { "defaultCollection": "@ngrx/schematics" }
3、創(chuàng)建 Store
ng g store State --root --module app.module.ts --statePath store --stateInterface AppState
4、創(chuàng)建 Action
ng g action store/actions/counter --skipTests
import { createAction } from "@ngrx/store" export const increment = createAction("increment") export const decrement = createAction("decrement")
5、創(chuàng)建 Reducer
ng g reducer store/reducers/counter --skipTests --reducers=../index.ts
import { createReducer, on } from "@ngrx/store" import { decrement, increment } from "../actions/counter.actions" export const counterFeatureKey = "counter" export interface State { count: number } export const initialState: State = { count: 0 } export const reducer = createReducer( initialState, on(increment, state => ({ count: state.count + 1 })), on(decrement, state => ({ count: state.count - 1 })) )
6、創(chuàng)建 Selector
ng g selector store/selectors/counter --skipTests
import { createFeatureSelector, createSelector } from "@ngrx/store" import { counterFeatureKey, State } from "../reducers/counter.reducer" import { AppState } from ".." export const selectCounter = createFeatureSelector<AppState, State>(counterFeatureKey) export const selectCount = createSelector(selectCounter, state => state.count)
7、組件類觸發(fā) Action、獲取狀態(tài)
import { select, Store } from "@ngrx/store" import { Observable } from "rxjs" import { AppState } from "./store" import { decrement, increment } from "./store/actions/counter.actions" import { selectCount } from "./store/selectors/counter.selectors" export class AppComponent { count: Observable<number> constructor(private store: Store<AppState>) { this.count = this.store.pipe(select(selectCount)) } increment() { this.store.dispatch(increment()) } decrement() { this.store.dispatch(decrement()) } }
8、組件模板顯示狀態(tài)
<button (click)="increment()">+</button> <span>{{ count | async }}</span> <button (click)="decrement()">-</button>
Action Payload
1、在組件中使用 dispatch 觸發(fā) Action 時傳遞參數(shù),參數(shù)最終會被放置在 Action 對象中。
this.store.dispatch(increment({ count: 5 }))
2、在創(chuàng)建 Action Creator 函數(shù)時,獲取參數(shù)并指定參數(shù)類型。
import { createAction, props } from "@ngrx/store" export const increment = createAction("increment", props<{ count: number }>())
export declare function props<P extends object>(): Props<P>;
3、在 Reducer 中通過 Action 對象獲取參數(shù)。
export const reducer = createReducer( initialState, on(increment, (state, action) => ({ count: state.count + action.count })) )
MetaReducer
metaReducer 是 Action -> Reducer 之間的鉤子,允許開發(fā)者對 Action 進行預(yù)處理 (在普通 Reducer 函數(shù)調(diào)用之前調(diào)用)。
function debug(reducer: ActionReducer<any>): ActionReducer<any> { return function (state, action) { return reducer(state, action) } } export const metaReducers: MetaReducer<AppState>[] = !environment.production ? [debug] : []
Effect
需求:在頁面中新增一個按鈕,點擊按鈕后延遲一秒讓數(shù)值增加。
1、在組件模板中新增一個用于異步數(shù)值增加的按鈕,按鈕被點擊后執(zhí)行 increment_async
方法
<button (click)="increment_async()">async</button>
2、在組件類中新增 increment_async
方法,并在方法中觸發(fā)執(zhí)行異步操作的 Action
increment_async() { this.store.dispatch(increment_async()) }
3、在 Action 文件中新增執(zhí)行異步操作的 Action
export const increment_async = createAction("increment_async")
4、創(chuàng)建 Effect,接收 Action 并執(zhí)行副作用,繼續(xù)觸發(fā) Action
ng g effect store/effects/counter --root --module app.module.ts --skipTests
2. NgRx CLI
ng config cli.defaultCollection @ngrx/schematics
import { Injectable } from "@angular/core"
import { Actions, createEffect, ofType } from "@ngrx/effects"
import { increment, increment_async } from "../actions/counter.actions"
import { mergeMap, map } from "rxjs/operators"
import { timer } from "rxjs"
// createEffect
// 用于創(chuàng)建 Effect, Effect 用于執(zhí)行副作用.
// 調(diào)用方法時傳遞回調(diào)函數(shù), 回調(diào)函數(shù)中返回 Observable 對象, 對象中要發(fā)出副作用執(zhí)行完成后要觸發(fā)的 Action 對象
// 回調(diào)函數(shù)的返回值在 createEffect 方法內(nèi)部被繼續(xù)返回, 最終返回值被存儲在了 Effect 類的屬性中
// NgRx 在實例化 Effect 類后, 會訂閱 Effect 類屬性, 當(dāng)副作用執(zhí)行完成后它會獲取到要觸發(fā)的 Action 對象并觸發(fā)這個 Action
// Actions
// 當(dāng)組件觸發(fā) Action 時, Effect 需要通過 Actions 服務(wù)接收 Action, 所以在 Effect 類中通過 constructor 構(gòu)造函數(shù)參數(shù)的方式將 Actions 服務(wù)類的實例對象注入到 Effect 類中
// Actions 服務(wù)類的實例對象為 Observable 對象, 當(dāng)有 Action 被觸發(fā)時, Action 對象本身會作為數(shù)據(jù)流被發(fā)出
// ofType
// 對目標(biāo) Action 對象進行過濾.
// 參數(shù)為目標(biāo) Action 的 Action Creator 函數(shù)
// 如果未過濾出目標(biāo) Action 對象, 本次不會繼續(xù)發(fā)送數(shù)據(jù)流
// 如果過濾出目標(biāo) Action 對象, 會將 Action 對象作為數(shù)據(jù)流繼續(xù)發(fā)出
@Injectable()
export class CounterEffects {
constructor(private actions: Actions) {
// this.loadCount.subscribe(console.log)
}
loadCount = createEffect(() => {
return this.actions.pipe(
ofType(increment_async),
mergeMap(() => timer(1000).pipe(map(() => increment({ count: 10 }))))
)
})
}
?? 3. Storeng store State --root --module app.module.ts --statePath store --stateInterface AppState
4. Create Action
ng g action store/actions/counter --skipTests
/* { ids: [1, 2], entities: { 1: { id: 1, title: "Hello Angular" }, 2: { id: 2, title: "Hello NgRx" } } } */ export interface State extends EntityState<Todo> {}5. ??? ??
ng g ??? store/reducers/counter --skipTests --reducers=../index.ts < /code><p><pre class='brush:php;toolbar:false;'>export const adapter: EntityAdapter<Todo> = createEntityAdapter<Todo>()
// 獲取初始狀態(tài) 可以傳遞對象參數(shù) 也可以不傳
// {ids: [], entities: {}}
export const initialState: State = adapter.getInitialState()</pre></p><p>6. ??? ???</p><p></p><code>ng g ??? store/selectors/counter --skipTests
// selectTotal 獲取數(shù)據(jù)條數(shù) // selectAll 獲取所有數(shù)據(jù) 以數(shù)組形式呈現(xiàn) // selectEntities 獲取實體集合 以字典形式呈現(xiàn) // selectIds 獲取id集合, 以數(shù)組形式呈現(xiàn) const { selectIds, selectEntities, selectAll, selectTotal } = adapter.getSelectors();7. ?? ?? ???? ??? ????? ??? ?????
export const selectTodo = createFeatureSelector<AppState, State>(todoFeatureKey) export const selectTodos = createSelector(selectTodo, selectAll)
8. ?? ?? ??? ?? ??
import { StoreRouterConnectingModule } from "@ngrx/router-store" @NgModule({ imports: [ StoreRouterConnectingModule.forRoot() ] }) export class AppModule {}Action Payload1. Action? ????? ?? ?? ???? ????? ????? ? ?? ??? ???? ?? ??? ?? Action ??? ?????.
import * as fromRouter from "@ngrx/router-store"
export interface AppState {
router: fromRouter.RouterReducerState
}
export const reducers: ActionReducerMap<AppState> = {
router: fromRouter.routerReducer
}
2. Action Creator ??? ??? ? ????? ???? ???? ??? ?????. // router.selectors.ts
import { createFeatureSelector } from "@ngrx/store"
import { AppState } from ".."
import { RouterReducerState, getSelectors } from "@ngrx/router-store"
const selectRouter = createFeatureSelector<AppState, RouterReducerState>(
"router"
)
export const {
// 獲取和當(dāng)前路由相關(guān)的信息 (路由參數(shù)、路由配置等)
selectCurrentRoute,
// 獲取地址欄中 # 號后面的內(nèi)容
selectFragment,
// 獲取路由查詢參數(shù)
selectQueryParams,
// 獲取具體的某一個查詢參數(shù) selectQueryParam('name')
selectQueryParam,
// 獲取動態(tài)路由參數(shù)
selectRouteParams,
// 獲取某一個具體的動態(tài)路由參數(shù) selectRouteParam('name')
selectRouteParam,
// 獲取路由自定義數(shù)據(jù)
selectRouteData,
// 獲取路由的實際訪問地址
selectUrl
} = getSelectors(selectRouter)
// home.component.ts
import { select, Store } from "@ngrx/store"
import { AppState } from "src/app/store"
import { selectQueryParams } from "src/app/store/selectors/router.selectors"
export class AboutComponent {
constructor(private store: Store<AppState>) {
this.store.pipe(select(selectQueryParams)).subscribe(console.log)
}
}
3. Reducer? Action ??? ?? ????? ?????.
rrreeeMetaReducer
metaReducer? Action -> Reducer ??? ?? ??? ???? Action(?? Reducer ??? ???? ?? ???)? ???? ? ????.rrreee
Effect
?? ??: ???? ??? ???? ??? ??? ? 1? ?? ???? ?? ????. 1. ???? ???? ??? ? ??? ?? ??? ?????. ??? ??? ? increment_async
???? ?????.rrreee
rrreee3. Action ??rrreee
4? ??? ??? ???? Action? ???? Action? ?? Side Effect? ?????. ???? Action????ng g effect store/??/counter --root --module app.module.ts --skipTests????Effect ??? ??????. ?? ??? ?? ???? ???? ???. ??rrreee????Entity??????????1? ?? ????. ??????????Entity? ???? ???? ???? ???? ??? ?????. ????NgRx? ??? ??? ??? ????, ? ??? ???? ???? ???? ???? ??? ????. ????????2 ??????https://ngrx.io/guide/entity/adapter#adapter-collection-methods????????4. Selector??????rrreeerrreee????Router Store??????????1. ?? ?? ??1) ?? ?? ??rrreee??2) ??? ??? Store??rrreee??????2? ???? ??? ??? ?? ?? ???? ??????????rrreeerrreee??? ?? ????? ?? ??? ??? ??????? ?????? ?????! ! ??? ??? ?? ?? ?? ??? NgRx? ?? ??? ??? ?? ?????. ??? ??? PHP ??? ????? ?? ?? ??? ?????!

? AI ??

Undress AI Tool
??? ???? ??

Undresser.AI Undress
???? ?? ??? ??? ?? AI ?? ?

AI Clothes Remover
???? ?? ???? ??? AI ?????.

Clothoff.io
AI ? ???

Video Face Swap
??? ??? AI ?? ?? ??? ???? ?? ???? ??? ?? ????!

?? ??

??? ??

???++7.3.1
???? ?? ?? ?? ???

SublimeText3 ??? ??
??? ??, ???? ?? ????.

???? 13.0.1 ???
??? PHP ?? ?? ??

???? CS6
??? ? ?? ??

SublimeText3 Mac ??
? ??? ?? ?? ?????(SublimeText3)

Angular.js? ?? ??????? ??? ?? ???? ???? ? ?? JavaScript ??????. HTML ??? ??? ??? ???? ??????? ??? ??? ??? ???? ??? ? ????. Angular.js? ??? ??, ???? ? ????? ? ??? ?? ??? ??? ?????. ?? ??? ? ?? ??? ?? ?? ??? ?????. ? ?????? Ubuntu24? Angular? ???? ??? ?? ?????. ?? Node.js? ???? ???. Node.js? ?? ??? JavaScript ??? ??? ? ?? ??? ChromeV8 ?? ??? JavaScript ?? ?????. Ub? ????

???? ??? ???? ???? ??? ?????? ?? ?? ?? ?????? ???? Monaco-Editor? ?? ??? ??? ????.

???? ??? ??? ?? ????? ?? ??? ????? ???? ???? ????. PHP? Angular? ????? ??? ?? ???? ? ?? ?????. PHP? ?? ??, ?? ??? ??, ??? ?? ??? ?? ??? ??? ? ?? ??? ???? ?????. Angular? ?? ??? ??????? ???? ?? ???? ? ??????? ???? ? ??? ? ?? JavaScript ????????. ? ????? ????? ??? PHP? Angular? ???? ??? ??? ???? ??? ?????.

? ?? ???? ???? Angular? ??? Angular? ??? ????(Standalone Component)? ???? ???? ? ??? ??? ????.

? ?? Angular? ?? ??? NgRx? ?? ???? ??? ???? NgRx ?? ??? ???? ?? ? ????.

??? ????(Angular Universal)? ????? ????? ? ?? SEO ??? ???? ? ??? ? ? ????!

??? ?? ? ???????? ?? ??? ?? ? ?????. ? ??????? ?? ?? ?? ???? ?? ??? ????? ???? ?? ?????. ? ????? ??? Angular? Node.js? ??? ???? ???? ??? ? ? ????. ?? ?? ??? ?? ?? ?? ????? ???? ?? ?? ?? ???? ???????. ???? ??? ??? ??? ??? ????? ???? ???? ?????. ??? ? ??????? ???? ????? ???? ?????. ??? ???? ???????? ?? ??? ??? ???? ??? ????, ?? ??? ?? ??? ???? ????? ?? ID? ????. ??? ?? ??????? ?? ???? ?????.

Angular ?????? ?? ??? ?? ?? ?? ??? ?? ?? ??? ?? ?? ????. ? ??? ??? ?? ?? ???? ???? ???? ???? ? ?? ??? ???? ??? ????? ????? ?????. CSS ?? ??? ????? ???? Angular ?? ??? ??? ??? ???? ??? ????? ???? ?? ? ????.
