狀態管理器 - Redux

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/

注:此文章爲個人筆記,不作標準答案,僅供參考,請以官方文檔爲準。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章