Redux

Redux
    概述
        Redux(作者:Dan Abramov,同时也是React核心团队成员)是 JavaScript 状态容器,提供具有响应式特性的全局状态管理
        作用类似于Vue.js中的Vuex,可以在组件间共享全局状态数据
        Redux可以运行于Node.js服务器端应用、Web客户端应用、原生App应用;也可以配合jQuery、React、Angular等框架组合使用。
    面试题:Redux和H5中的sessionStorage / localStorage的区别?
        ① Redux是保存在内存中的,刷新页面即恢复初始值,无法持久化保存;sessionStorage保存在内存中,localStorage保存在磁盘中,刷新也不会丢失
        ② Redux中的数据具有响应式特征,订阅了该数据的组件都会自动发生改变;sessionStorage / localStorage中的数据不具备响应式特征
        ③ Redux可以用于Web客户端应用、原生App应用、Node.js服务器端应用;sessionStorage / localStorage主要应用于Web客户端页面间的数据共享
    四大核心概念
        ① state
            应用在当前时刻需要记录的需要具备响应式特性的数据,尤其是需要在多个组件间共享的数据,故需要集中存储
            例如:服务器响应数据、缓存数据、本地生成尚未持久化到服务器的数据、UI 状态数据等
            React组件也有“状态(state)”数据,二者有本质的不同
                ① Redux中的state是没有setState()方法的,即不能随意修改
                ② Redux中的state用于多组件共享,而React中的state仅在当前组件中使用
                ③ React中的state数据具有“合并”特性;而Redux中的数据修改不具备“合并”特性
        ② action
            要对数据执行的动作;要想更新 state 中的数据,需要发起一个 action
            每个action都是一个普通 JavaScript 对象,用来描述发生想要对state执行什么操作
            每个action都需要有一个type属性,描述操作的目标
                { type: 'CHANGE_NEWS_PNO',  pno: 6 }
                { type: 'TOGGLE_AGREEMENT',  value: true }
                { type: 'SET_FAVORITE_TOPICS',  list: [10, 25, 31] }
        ③ reducer
            指定对 state 执行 action 动作应该如何实现
            reducer是一些纯函数,接收当前的state和要执行的action作为参数,返回根据action修改后的新的state对象,从而实现action想要实现的操作
            function appReducer(state = initState, action){
            if(action.type === ' CHANGE_NEWS_PNO '){
                    return { ...state,  newsPageNum: action.pno }
            }else if(action.type === ' TOGGLE_AGREEMENT '){
                    return { ...state,  agreementChecked: action.value }
            }else if(action.type === ' SET_FAVORITE_TOPICS '){
                    return { ...state,  favoriteTopics: action.list }
            }else {
                    return state
            }
}
        ④ store
            状态数据存储仓库; 所有的状态最终都被存储到一个唯一的“存储仓库”中
            仓库的职责
                ① 存储所有的state
                ② 提供 getState( ) 供外界查询数据状态 —— 返回全部的状态数据
                ③ 提供 dispatch(action) 供外界更新状态
                ④ 通过 subscribe(listener) 注册监听器
                ⑤ 通过 subscribe(listener) 返回的函数注销监听器
            
    演示1:在Node.js应用中使用Redux

const { createStore } = require("redux");

// 概念1state
let inisState = {
    registeredUser: 0, //注册用户数
    onlineUser: 0, //在线用户数
};
//概念2action
// {type:"LOGIN"}
// {type:"LOGOUT"}
// {type:"ONE_REGISTER"}
// {type:"BATCH_REGISTER",count:50}
//概念3reducer
function appReducer(state = inisState, action) {
    console.log("state update");
    if (action.type === "LOGIN") {
        return { ...state, onlineUser: state.onlineUser + 1 };
    } else if (action.type === "LOGOUT") {
        return { ...state, onlineUser: state.onlineUser - 1 };
    } else if (action.type === "ONE_REGISTER") {
        return { ...state, registeredUser: state.registeredUser + 1 };
    } else if (action.type === "BATCH_REGISTER") {
        return { ...state, registeredUser: state.registeredUser + action.count };
    } else {
        return state;
    }
}
//概念4store
let store = createStore(appReducer);

// 查看仓库中目前的状态
// console.log(store.getState());
// 订阅仓库的状态更新
store.subscribe(() => {
    console.log("收到订阅消息,仓库状态改变");
    console.log(store.getState());
});
// 使用定时器修改仓库的状态
setInterval(() => {
    store.dispatch({ type: "ONE_REGISTER" });
}, 1000);

setInterval(() => {
    store.dispatch({type:"BATCH_REGISTER",count:10});
}, 3000);

    演示2:在React应用中使用Redux(单一文件)

@app.js
import React, { useState } from "react";
import { createStore } from "redux";
// state
let initState = {
    buyCount: 1,
};
// action
// {type:"ENCREASE"}
// {type:"DECREASE"}

// reducer
function appReducer(state = initState, action) {
    console.log("state updated");
    if (action.type === "ENCREASE") {
        return { ...state, buyCount: state.buyCount + 1 };
    } else if (action.type === "DECREASE") {
        let buyCount = state.buyCount - 1;
        buyCount = buyCount < 0 ? 0 : buyCount;
        return { ...state, buyCount };
    } else {
        return state;
    }
}
//store
let store = createStore(appReducer);
function CaryShow() {
    let [count, setCount] = useState(store.getState().buyCount);
    // 订阅仓库状态的修改
    store.subscribe(() => {
        setCount(store.getState().buyCount);
    });
    return <div>当前购物车中商品数量:{count}</div>;
}
function CartModify() {
    return (
        <>
            <button onClick={() => store.dispatch({ type: "DECREASE" })}>
                -
            </button>
            <button onClick={() => store.dispatch({ type: "ENCREASE" })}>
                +
            </button>
        </>
    );
}
export default function App() {
    return (
        <div>
            <CaryShow></CaryShow>
            <hr></hr>
            <CartModify></CartModify>
        </div>
    );
}


    演示3:在React应用中使用Redux(多个文件)

@context.js
import { createStore } from "redux";
import React from "react";

// state
let initState = {
    buyCount: 5,
};
// action
// {type:"ENCREASE"}
// {type:"DECREASE"}

// reducer
function appReducer(state = initState, action) {
    console.log("state updated");
    if (action.type === "ENCREASE") {
        return { ...state, buyCount: state.buyCount + 1 };
    } else if (action.type === "DECREASE") {
        let buyCount = state.buyCount - 1;
        buyCount = buyCount < 0 ? 0 : buyCount;
        return { ...state, buyCount };
    } else {
        return state;
    }
}
// store

export let store = createStore(appReducer);
//上下文对象=为所有自足案件提供共享数据:store
let StoreContext = React.createContext(store);
export default StoreContext;
@index.js
import React from "react";
import ReactDOM from "react-dom/client";
import CartModify from "./components/CartModify";
import CartShow from "./components/CartShow";
import StoreContext, { store } from "./context";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
    <StoreContext.Provider value={store}>
        <CartShow></CartShow>
        <hr />
        <CartModify></CartModify>
    </StoreContext.Provider>
);
@components\CartModify.js
import React, { useContext } from "react";
import StoreContext from "../context";
import mapDispatch from "./mapDispatch";

// export default function CartModify() {
//     let ctx = useContext(StoreContext);
//     return (
//         <div>
//             <button onClick={() => ctx.dispatch({ type: "DECREASE" })}>
//                 -
//             </button>
//             <button onClick={() => ctx.dispatch({ type: "ENCREASE" })}>
//                 +
//             </button>
//         </div>
//     );
// }
function CartModify(props) {
    return (
        <div>
            <button onClick={() => props.dec()}>-</button>
            <button onClick={() => props.enc()}>+</button>
        </div>
    );
}
export default mapDispatch(CartModify);
@components\CartShow.js
import React, { useContext, useState } from "react";
import StoreContext from "../context";
import mapStateToProps from "./mapStateToProps";

// export default function CartShow() {
//     let ctx = useContext(StoreContext);
//     let [count, setCount] = useState(ctx.getState().buyCount);
//     ctx.subscribe(() => {
//         setCount(ctx.getState().buyCount);
//     });
//     return <div>当前购物车数量:{count}</div>;
// }
function CartShow(props) {
    return <div>当前购物车数量:{props.bc}</div>;
}
export default mapStateToProps(CartShow);
@components\mapDispatch.js
import { useContext } from "react";
import StoreContext from "../context";

// 将store的dispatch(action)方法映射为指定组件的props
export default function mapDispatch(UserComponent) {
    function NewComponent(props) {
        let ctx = useContext(StoreContext);
        let enc = () => {
            ctx.dispatch({ type: "ENCREASE" });
        };
        let dec = () => {
            ctx.dispatch({ type: "DECREASE" });
        };
        return <UserComponent {...props} enc={enc} dec={dec}></UserComponent>;
    }
    return NewComponent;
}
@components\mapStateToProp.js
import { useContext, useState } from "react";
import StoreContext from "../context";

// 将store中的状态数据,映射为制定组件的props
export default function mapStateToProps(UserComponent) {
    function NewComponent(props) {
        let ctx = useContext(StoreContext);
        let [count, setCount] = useState(ctx.getState().buyCount);
        ctx.subscribe(() => {
            setCount(ctx.getState().buyCount);
        });
        return <UserComponent {...props} bc={count}></UserComponent>;
    }
    return NewComponent;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值