Redux 是 JavaScript 狀態容器,提供可預測化的狀態管理。
Redux通常結合react一起使用,但除了react還可以與其他框架一起使用,如:angular、vue等;
一、安裝
npm install redux -s
很多時候,我們會搭配react使用,我們需要安裝以下:
npm install react-redux -s
二、基礎
下面將以一個操作用戶和商品的功能爲例說明。
項目最後完成工程結構:
store
actionTypes.js // 存放行爲常量
index.js // redux工程入口,創建store
actions // 存放各模塊action
Goods.js
User.js
reducers // 存放各模塊reducer
Goods.js
User.js
1、創建行爲常量文件
創建一個存放行爲常量文件,提供 action 和 reducer 導入使用。
// actionTypes.js
export const ADD_USER = "ADD_USER"; // 添加用戶
export const UPDATE_USER = "UPDATE_USER"; // 更新用戶
export const DELETE_USER = "DELETE_USER"; // 刪除用戶
export const ADD_GOODS = "ADD_GOODS"; // 添加商品
export const UPDATE_GOODS = "UPDATE_GOODS"; // 更新商品
export const DELETE_GOODS = "DELETE_GOODS"; // 刪除商品
2、創建action:
action是一個是把數據從應用傳到 store 的有效載荷。它是 store 數據的唯一來源。一般來說你會通過store.dispatch() 將 action 傳到 store。
我們約定,action一般包含type字段,type一般爲常量,我們定義在actionTypes.js中。action還會需要一個載體屬性,我們以payload作爲載體屬性,傳遞數據給reducer。
redux一般建議我們在項目較大時應該以模塊分割action
actions/User.js:
// actions/User.js
import { ADD_USER, UPDATE_USER, DELETE_USER } from "../actionTypes"; // 按需導入action類型
// 添加用戶
export function addUser(userName,gender,age) {
return {
type: ADD_USER,
payload: {
userName,
gender,
age
}
}
}
// 更新用戶
export function updateUser(userName,gender,age) {
return {
type: UPDATE_USER,
payload: {
userName,
gender,
age
}
}
}
// 刪除用戶
export function deleteUser(userName,gender,age) {
return {
type: DELETE_USER,
payload: {
userName,
gender,
age
}
}
}
actions/Goods.js
// actions/Goods.js
import {ADD_GOODS, UPDATE_GOODS, DELETE_GOODS} from "../actionTypes"; // 按需導入action類型
// 添加商品
export function addGoods(id, goodsName, price, stock) {
return {
type: ADD_GOODS,
payload: {
id,
goodsName,
price,
stock
}
}
}
// 更新商品
export function updateGoods(id, goodsName, price, stock) {
return {
type: UPDATE_GOODS,
payload: {
id,
goodsName,
price,
stock
}
}
}
// 刪除商品
export function deleteGoods(id, goodsName, price, stock) {
return {
type: DELETE_GOODS,
payload: {
id,
goodsName,
price,
stock
}
}
}
3、創建reducer:
Reducers 指定了應用狀態的變化如何響應 action 併發送到 store 的,記住 actions 只是描述了有事情發生了這一事實,並沒有描述應用如何更新 state。
reducer接收兩個參數,第一個參數爲舊的state, 第二個參數爲action中載體payload,即新的state。
注意:我們不應該直接修改舊的state,我們始終應該返回一個新的state對象,我們應該對就state進行拷貝,然後在拷貝數據基礎上進行修改。這是redux能夠實現數據時光旅行的原因。
redux強調,我們不應該創建多個store,我們應該分割多個reducer來管理屬於自己的部分,然後通過合併爲一個reducers:
reducers/User.js
// reducers/User.js
import { ADD_USER, UPDATE_USER, DELETE_USER } from "../actionTypes"; // 按需導入action類型
const localState = [ // 初始數據,默認沒有數據,用於測試
{userName: '張三', gender: '男', age: 24},
{userName: '李四', gender: '男', age: 25},
]
export default function(state = localState, action) {
switch (action.type) {
case ADD_USER:
return [...state, action.payload];
case UPDATE_USER:
return state.map(item => item.userName === action.payload.userName ? action.payload : item);
case DELETE_USER:
return state.filter(item => item.userName !== action.payload.userName);
default:
return state;
}
}
reducers/Goods.js
// reducers/Goods.js
import {ADD_GOODS, UPDATE_GOODS, DELETE_GOODS} from "../actionTypes";
const localState = [
{id: 1, goodsName: '小米10', price: 3999, stock: 10000},
{id: 2, goodsName: '小米10Pro', price: 4999, stock: 2000},
]
export default function(state = localState, action) {
switch (action.type) {
case ADD_GOODS:
return [...state, action.payload];
case UPDATE_GOODS:
return state.map(item => item.id === action.payload.id ? action.payload : item);
case DELETE_GOODS:
return state.filter(item => item.id !== action.payload.id);
default:
return state;
}
}
4、創建index.js
此文件用於整合reducer,並創建store,
import { createStore, combineReducers } from "redux";
import User from './reducers/User'; // 導入reducer的User模塊
import Goods from './reducers/Goods'; // 導入reducer的Goods模塊
let reducers = combineReducers({User,Goods}) // 合併reducer
let store = createStore(reducers); // 創建store,如無需合併,可直接傳入reducer,如:createStore(User)
const unsubscribe = store.subscribe(() => { // 訂閱state的數據監聽。訂閱後會返回一個函數,我們可以通過對其調用取消訂閱。
console.log(store.getState())
})
export default store;
// unsubscribe(); // 取消訂閱
combineReducers :合併多個reducer。
store提供了一下方法:
getState():獲取當前state
dispatch(action):更新state
subscribe(listener):註冊state監聽。
到此所需的都已準備好,我們可以在任何一個頁面通過store對其進行調用。如下示例執行了數據的增刪改:
import store from './store/index'
import { addUser, updateUser, deleteUser } from './store/actions/User' // 獲取所需的用戶action
import {addGoods} from "./store/actions/Goods";
store.dispatch(addUser("王五", "男", 20)); // 添加一個用戶
store.dispatch(updateUser("李四", "男", 220)); // 更新一個名稱爲李四的用戶
store.dispatch(deleteUser("李四", "男", 22)); // 刪除名爲李四的用戶
store.dispatch(addGoods(3, "紅米K30 5G", 1999, 2000)); // 添加一個商品
官方中文文檔:https://www.redux.org.cn/
注:此文章爲個人筆記,不作標準答案,僅供參考,請以官方文檔爲準。