ngrx學習筆記

什么是ngrx
ngrx是Angular基于Rxjs的狀態管理,保存了Redux的核心概念,并使用RxJs擴展的Redux實現。使用Observable來簡化監聽事件和訂閱等操作。
在看這篇文章之前,已經假設你已了解rxjs和redux。
有條件的話請查看官方文檔進行學習理解。

所需包
ng add方式,會自動生成所需文件并在app.module.ts中導入,直接啟動項目即可,不報錯
?

ng add @ngrx/store
ng add @ngrx/store-devtools
ng add @ngrx/effects
ng add @ngrx/router-store

Angular的流程

compone.ts定義變量a
改變a
(沒有數據請求的) this.a = '';
(有數據請求的) this.a = this.services.search()類似的寫法
用ngrx后的Angular的基本流程

寫action.ts:為要改變數據的操作定義不同action
寫effects.ts(有數據請求的):通過判斷action.type,來發起service
寫reducer.ts:判斷action.type,返回新的store數據
component.ts:從store取數據
最后,告訴應用程序,你寫了這玩意

項目簡介
本項目的兩個demo,都掛在example模塊中

計數器-沒有數據請求 app/example/container/counter.component.ts
1、先寫action(減和重置的action在代碼里面,可自行查看)
?

// app/example/actions/counter.actions.ts
import { Action } from '@ngrx/store';export const INCREMENT = '[Counter] Increment';  export class IncrementAction implements Action {readonly type = INCREMENT;constructor() { }
}export type Actions= IncrementAction;

2、寫reducer(由于加不需要發送網絡請求,就不寫effect)

// app/example/reducer/counter.reducer.ts
import * as counter from '../actions/counter.actions';
// 定義接口,后續counter頁面如果有其他數據要保存,可以在這個State里面繼續添加,不要忘記在initialState也要加
export interface State {counter: number;
}
// 定義初始化數據
const initialState: State = {counter: 0
};
// 定義reducer 根據action type來處理狀態,改變對應數據
export function reducer(state = initialState, action: counter.Actions): State {switch (action.type) {case counter.INCREMENT: return {counter: state.counter + 1};default:return { ...state };}
}export const getCounter = (state: State) => state.counter;
// app/example/reducer/index.ts
import {createFeatureSelector, createSelector} from '@ngrx/store';// 第二步 導入我們的reducer文件
import * as fromCounter from './counter.reducer';export interface State {counter: fromCounter.State;
}
export const reducers = {counter: fromCounter.reducer
};//  將模塊example的所有數據掛在store上,命名為example,里面保存example模塊里面所有頁面的數據
export const getExampleState = createFeatureSelector<State>('example');// 計數器頁面
export const getCounterState = createSelector(getExampleState, (state: State) => state.counter);
export const getCounterCounter = createSelector(getCounterState, fromCounter.getCounter);

3、在模塊中導入reduecer,這樣就可以運行

// app/example/example.module.tsimport {StoreModule} from '@ngrx/store';
import {reducers} from './reducer';
@NgModule({imports: [StoreModule.forFeature('example', reducers) // 這個才是關鍵哦]
})
export class ExampleModule { }

4、到這一步了,我們的頁面就來操作并且取數據,增加啦

// src/example/container/counter.component.tsimport * as fromExample from '../../reducer';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import * as counterAction from '../../actions/counter.actions';export class CounterComponent {counter$: Observable<number>;constructor(private store: Store<fromExample.State>) {this.counter$ = store.select(fromExample.getCounterCounter);}increment() {this.store.dispatch(new counterAction.IncrementAction());}
}

頁面

// app/example/container/counter.component.html
<div class="container"><p class="title">計數器 沒有數據請求的ngrx demo</p><div class="btn-group"><button nz-button nzType="primary" (click)="increment()">加</button><span style="font-size: 18px;font-weight: bold">當前數:{{counter$ | async}}</span></div>
</div>

npm run start看一下頁面效果吧

搜索圖書-有數據請求的 src/app/example/containers/book-manage/book-manage.component.ts
1、寫action (src/app/example/actions/book-manage.actions.ts)看注釋

import { Action } from '@ngrx/store';
import {Book} from '../model/book';
// 搜索,然后搜索成功,兩件事情,分兩個action
export const SEARCH =           '[Book Manage] Search';
export const SEARCH_COMPLETE =  '[Book Manage] Search Complete';
// 搜索圖書需要帶書名稱來搜索,所以SearchAction有一個字符串類型的參數payload
export class SearchAction implements Action {readonly type = SEARCH;constructor(public payload: string) { }
}
// 搜索出結果后,圖書的信息我們將其定義類型為Book,結果放在數組里面,所以SearchCompleteAction 的參數是Book類型數組
export class SearchCompleteAction implements Action {readonly type = SEARCH_COMPLETE;constructor(public payload: Book[]) { }
}
export type Actions= SearchAction| SearchCompleteAction;

2、寫reducer(src/app/example/reducer/book-manage.reducer.ts)

import * as bookManage from '../actions/book-manage.actions';
import {Book} from '../model/book';
// book-manage頁面我們暫時定義一個list變量,用了存搜索圖書的結果,后續如果有其他變量,繼續在里面加
export interface State {list: Book[];
}
// 默認一開始搜索數據為空數組[]
const initialState: State = {list: []
};
// 當搜索成功后,更新state里面的list值
export function reducer(state = initialState, action: bookManage.Actions): State {switch (action.type) {case bookManage.SEARCH_COMPLETE:return {...state,list: action.payload};default:return { ...state };}
}export const getList = (state: State) => state.list;

3、更新reducer (src/app/example/reducer/index.ts)

import {createFeatureSelector, createSelector} from '@ngrx/store';
import * as fromCounter from './counter.reducer';
// 導入寫好的book-manage.reducer.ts
import * as fromBookManage from './book-manage.reducer';  
export interface State {counter: fromCounter.State;bookManage: fromBookManage.State;
}
export const reducers = {counter: fromCounter.reducer,bookManage: fromBookManage.reducer
};
export const getExampleState = createFeatureSelector<State>('example');
// 計數器
export const getCounterState = createSelector(getExampleState, (state: State) => state.counter);
export const getCounterCounter = createSelector(getCounterState, fromCounter.getCounter);
// 圖書管理
export const getBookManageState = createSelector(getExampleState, (state: State) => state.bookManage);
export const getBookManageList = createSelector(getBookManageState, fromBookManage.getList);

4、寫effect,檢測action類型,如果是search圖書行為,就發送網絡請求查結果(src/app/example/effects/book-manage.effect.ts)

import {Injectable} from '@angular/core';
import {Actions, Effect, ofType} from '@ngrx/effects';
import {Observable, of} from 'rxjs';
import {Action} from '@ngrx/store';import * as bookManage from '../actions/book-manage.actions';
import {BookManageService} from '../services/book-manage.service';
import {catchError, debounceTime, map, mergeMap, skip, takeUntil} from 'rxjs/operators';
import {BookResult} from '../model/book';@Injectable()
export class BookManageEffects {@Effect()searchBook$: Observable<Action> = this.actions$.pipe(ofType(bookManage.SEARCH),    // 判斷是不是搜索圖書的行為debounceTime(300),   // 做延遲,節省網絡請求mergeMap((action: bookManage.SearchAction) => {const nextSearch$ = this.actions$.pipe(ofType(bookManage.SEARCH), skip(1));return this.service.searchBooks(action.payload).pipe(takeUntil(nextSearch$),// 如果搜索成功,發送成功action并且帶入搜索結果map((data: BookResult) => ({type: bookManage.SEARCH_COMPLETE, payload: data.items})),// 如果搜索失敗404之類的原因,發送成功action,以及空數組更新結果catchError(() => of({type: bookManage.SEARCH_COMPLETE, payload: []})));}));constructor(private actions$: Actions, private service: BookManageService) {}
}

5、component獲取搜索結果和綁定搜索事件(src/app/example/containers/book-manage/book-manage.component.ts)

import { Component, OnInit } from '@angular/core';
import {Store} from '@ngrx/store';
import * as fromExample from '../../reducer';
import * as bookManageAction from '../../actions/book-manage.actions';
import {Observable} from 'rxjs';
import {Book} from '../../model/book';
@Component({selector: 'app-book-manage',templateUrl: './book-manage.component.html',styleUrls: ['./book-manage.component.css']
})
export class BookManageComponent implements OnInit {searchResult$: Observable<Book[]>;  // 搜索到的圖書列表constructor(private store: Store<fromExample.State>) {// 從store中選取圖書搜索結果this.searchResult$ = this.store.select(fromExample.getBookManageList);}ngOnInit() {}// 發送搜索行為search(bookName) {this.store.dispatch(new bookManageAction.SearchAction(bookName));}}

頁面(src/app/example/containers/book-manage/book-manage.component.html)

<div class="container"><app-search-input (search)="search($event)"></app-search-input><app-book-list [bookList]="searchResult$ | async"></app-book-list>
</div>

6、導入effect,否則會不起作用哦 (src/app/example/example.module.ts)

...
import {BookManageEffects} from './effects/book-manage.effect';
import {EffectsModule} from '@ngrx/effects';@NgModule({...imports: [EffectsModule.forFeature([BookManageEffects]),],

ngrx 入門_霞霞的博客的博客-CSDN博客_ngrx文檔

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247233.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247233.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247233.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解決RM刪除沒有釋放空間問題

www172-18-8-12 log]$ df -h Filesystem Size Used Avail Use% Mounted on/dev/vda1 120G 101G 20G 84% /devtmpfs 7.8G 0 7.8G 0% /devtmpfs 7.8G 0 7.8G 0% /dev/shmtmpfs 7.8G 601M 7.2G 8% /run 我刪除文件時&#xff0c;直接用的rm 沒有加參數lf,結果空間沒有釋放 文件已經…

.slice(0)

高手代碼里看到.slice(0)&#xff0c;查了下這樣寫的好處&#xff1a; 1.對原數組進行深拷貝&#xff0c;這樣進行一系列操作的時候就不影響原數組了&#xff1b; 2.將類數組對象轉化為真正的數組對象&#xff1a;var anchorArray [].slice.call(document.getElementsByTagN…

在線課程學習、科研科技視頻網站

最近在網絡學習課程&#xff0c;發現很多在線課程網站&#xff0c;與大家分享一下。本人新浪博客&#xff1a;http://blog.sina.com.cn/u/1240088994 公開課課程圖譜http://coursegraph.com/navigation/ 1. 網易公開課 http://open.163.com/&#xff1b; 網易TED http://…

對html2canvas的研究

介紹 該腳本允許您直接在用戶瀏覽器上截取網頁或部分網頁的“屏幕截圖”。屏幕截圖基于DOM&#xff0c;因此它可能不是真實表示的100&#xff05;準確&#xff0c;因為它沒有制作實際的屏幕截圖&#xff0c;而是根據頁面上可用的信息構建屏幕截圖。 這個怎么運作 該腳本遍歷其加…

[Vue warn]: You are using the runtime-only build of Vue 牽扯到Vue runtime-compiler與runtime-only區別

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build. 1. Vue的編譯渲染過程 template --> ast --> render函數 -…

親歷2013年TED大會:全球最潮靈感大會

本文轉自&#xff1a;http://mooc.guokr.com/opinion/436837/ 本文由《外灘畫報》供稿 文/華琪&#xff08;發自美國&#xff09; 編輯/吳慧雯 什么是TED的世界&#xff1f;在這里&#xff0c;你可以輕易發現各種名人出沒的痕跡&#xff0c;和各個領域里最具遠見卓識和創造…

Java生鮮電商平臺-電商會員體系系統的架構設計與源碼解析

Java生鮮電商平臺-電商會員體系系統的架構設計與源碼解析 說明&#xff1a;Java生鮮電商平臺中會員體系作為電商平臺的基礎設施&#xff0c;重要性不容忽視。我去年整理過生鮮電商中的會員系統&#xff0c;但是比較粗&#xff0c;現在做一個最好的整理架構. 設計電商會員體系需…

為什么要上大學?

為了讓自己成為更有意思的人。 &#xff08;文&#xff0f;美國圣母大學哲學教授 Gary Gutting&#xff09;再不久&#xff0c;千千萬萬的大學生又將走完一個學期。他們中的很多人以及他們的家人&#xff0c;可能為剛剛過去的幾個月或是幾年投入了相當可觀的時間、努力以及金錢…

React AntD 表格查看修改時默認選中幾行數據

hook定義selectedRowKeys const [selectedRowKeys, setSelectedRowKeys] useState([]); const [selectedRowsState, setSelectedRows] useState([]); 初始化時利用setSelectedRowKeys給selectedRowKeys塞值,時行數據的rowKey的數組。 設置table屬性rowSelection <Table…

python面向對象三大特性、類的約束、print帶顏色輸出及super補充

面向對象三大特性、類的約束、print帶顏色輸出及super補充 簡述&#xff1a; python面向對象的三大特性&#xff1a; 1.繼承是一種創建新類的方式&#xff0c;在python中&#xff0c;新建的類可以繼承一個或多個父類&#xff0c;父類又可稱為基類或超類&#xff0c;新建的類稱為…

dayjs也可回顯AntD DatePicker的值

遇到的問題&#xff1a;react 使用AntD 表單里有多個RangePicker,查看修改時要回顯值。 antd的DatePicker需要的是moment對象。但是項目里引的是dayjs庫 解決方式&#xff1a; 方式一:直接多引moment.js庫&#xff0c;字符串轉moment對象 moment(2022-02) 方式二:不甘心引兩…

打造“神犇”是教育的未來嗎?

這年頭&#xff0c;品學兼優、身懷特長的“神犇”&#xff0c;拼的不僅是天賦異稟和后天努力&#xff0c;更是身后爹媽的錢包&#xff0c;而本該實現社會公平的教育&#xff0c;反而加速和凝固了社會的不公。 高等教育的終極目標真的是造就學業超人嗎&#xff1f;《紐約時報》刊…

洛谷 P3243 【[HNOI2015]菜肴制作】

第一眼看到這題&#xff0c;頓時懵逼&#xff0c;一個 \(SB\) 拓撲序竟然是黑題&#xff0c;當場笑噴。 \(Of\) \(course\)&#xff0c;這題我是用堆做的。&#xff08;其實是優先隊列&#xff0c;手寫堆這么垃圾我怎么可能會用呢&#xff09; \((1)\) 首先建圖。如果 \(x\) 需…

AntD 官網樣例 InputRef報錯原因

在官網可編輯表格typescript樣例里 const inputRef useRef<InputRef>(null); InputRef項目報錯原因是ant design的版本問題! antd 4.19版本重寫了input 可通過InputRef來使用input組件的ref

電路原理圖檢查的十大步驟詳解

最近一直在做嵌入式系統&#xff0c;畫原理圖。最后&#xff0c;為了保證原理圖準確無誤&#xff0c;檢查原理圖花費我近兩周的時間&#xff0c;在此&#xff0c;把我在檢查原理圖方面的心得體會總結在此&#xff0c;供大家參考&#xff0c;說得不對的地方歡迎大家指出。 往往我…

亞倫?斯沃茨:怎樣有效利用時間

編者按&#xff1a;今天是著名黑客亞倫?斯沃茨&#xff08;Aaron Swartz&#xff09;頭七的日子。斯沃茨14歲就參與創造RSS 1.0規格的制定&#xff0c;曾在斯坦福大學就讀了一年&#xff0c;是社交新聞網站Reddit的三位創始人之一……斯沃茨自殺時才年僅26歲。這26歲的短暫生命…

AntD 可編輯行表格

本地數據代碼模板自用,官網例子改改 // 編輯行的自定義表格 import React, { useState } from "react"; import {Table,Input,InputNumber,Popconfirm,Form,Typography,Divider, } from "antd";interface Item {key: string;name: string;age: number;add…

SharePoint 2013 - System Features

1. Embed Information & Convert to PDF 功能&#xff0c;在文檔的preview界面&#xff08;hover panel&#xff09;; 2. Share功能可以選擇是否發送郵件 -- Done 4. Shredded Storage, 將文檔的內容和每次的更改分開存儲&#xff0c;每次只存儲更改的內容&#xff0c;而不…

三心二意,助你好運?

經驗說&#xff1a;做事要專心致志。 實驗說&#xff1a;專心致志常常讓人缺少一雙發現的眼睛。 專心致志從來都被當做一個美德來歌頌。從來我們就認為要想成為偉大的人就必須要像牛頓老師那樣把鐘當成吃的放到鍋里煮才行&#xff0c;至少至少也得有能在集市上看書的本事。否則…

React Antd Upload自定義上傳customRequest

單獨的上傳圖片接口要傳參,action方式不太適合,需要使用自定義上傳customRequest覆蓋 公司代碼不可弄,就發一個可用的demo例子 import React, { useState } from "react"; import { render } from "react-dom"; import "antd/dist/antd.css"; i…