Redux相关源码:可以理解为主,但不要求一定都会写
redux不会,虽然也有一些其他的替代方案:mobx,但是基本可以宣告react阵亡了
VUE->Vuex
Redux生态圈中的知识
- redux react-redux redux中间件
- mobx 类的装饰器
- react-router-dom v5/v6
- redux-saga/dva/umi
- fetch及其二次封装
- antd pro
复合组件通信:
- 父子通信“具备相同父亲的兄弟组件”:props属性 “基于ref”
- 祖先和后代“具备相同祖先的平行组件”:context上下文
redux/react-redux 也是实现组件之间的通信技术“插件”
不管任何类型的组件,都可以基于这种方法,实现组件通信
公共状态管理方案
后期实战开发中,父子组件一般是基于: props/ref/redux其余组件的通信一般都是基于redux管理的
三个组件中,都需要用到创建的store容器
我在根组件中,导入store,把其放在上下文中,后期其他组件需要,只要是它的后代组件,则直接获取使用即可!!!
redux的使用
import { createStore } from 'redux';
/* 管理员:修改STORE容器中的公共状态 */
let initial = {
supNum: 10,
oppNum: 5
}
const reducer = function reducer(state = initial, action) {
// state: 存储STORE容器中的公共状态“最开始没有的时候,赋值初始状态值initial”
// action: 每一次基于dispatch派发的时候,传递进来的行为对象“要求必须具备type属性,存储派发的行为标识”
// 接下来我们需要基于派发的行为标识,修改STORE容器中的公共状态信息
switch(action.type) {
case "VOTE_SUP":
break;
case "VOTE_OPP":
break;
default:
}
// return的内容,会整体替换STORE容器中的内容
return state;
}
// 创建STORE公共容器
const store = createStore(reducer);
store.dispatch({
type: "VOTE_SUP",
step: 10
});
export default store;
通过上下文获取store
- store.js
import { createStore } from 'redux';
/* 管理员:修改STORE容器中的公共状态 */
let initial = {
supNum: 10,
oppNum: 5
}
const reducer = function reducer(state = initial, action) {
// state: 存储STORE容器中的公共状态“最开始没有的时候,赋值初始状态值initial”
// action: 每一次基于dispatch派发的时候,传递进来的行为对象“要求必须具备type属性,存储派发的行为标识”
// 接下来我们需要基于派发的行为标识,修改STORE容器中的公共状态信息
switch(action.type) {
case "VOTE_SUP":
state.supNum++;
break;
case "VOTE_OPP":
state.oppNum++;
break;
default:
}
// return的内容,会整体替换STORE容器中的内容
return state;
}
// 创建STORE公共容器
const store = createStore(reducer);
export default store;
- index.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.sass';
import Vote from './views/Vote';
import { ConfigProvider } from 'antd';
import store from './store';
import ThemeContext from './ThemeContext';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ConfigProvider>
<ThemeContext.Provider value={
store
}>
<Vote></Vote>
</ThemeContext.Provider>
</ConfigProvider>
);
- vote.jsx
import React, { useContext, useEffect, useState } from "react";
import "./Vote.sass";
import VoteMain from "./VoteMain";
import VoteFooter from "./VoteFooter";
import ThemeContext from "../ThemeContext";
function Vote() {
const { store } = useContext(ThemeContext);
const { supNum, oppNum } = store.getState();
// 组件第一次渲染完毕之后,把组件更新的方法,放在STORE的事件池中
// const [ num, setNum ] = useState(0);
// const update = () => {
// setNum(num + 1);
// }
// useEffect(() => {
// // let unsubscribe = store.subscribe(让组件更新的方法);
// // 把让组件更新的方法放在STORE的事件池中
// // 返回的unsubscribe方法执行,可以把刚才放入事件池中的方法移除掉
// let unsubscribe = store.subscribe(update);
// return () => {
// unsubscribe();
// }
// }, [ num ])
const [ _, setNum ] = useState(0);
useEffect(() => {
// let unsubscribe = store.subscribe(让组件更新的方法);
// 把让组件更新的方法放在STORE的事件池中
// 返回的unsubscribe方法执行,可以把刚才放入事件池中的方法移除掉
store.subscribe(() => {
setNum(new Date().valueOf());
});
// return () => {
// unsubscribe();
// }
}, [])
return <div className="vote-box">
<div className="header">
<h2 className="title">
React是很棒的前端框架
</h2>
<span className="num"> { supNum + oppNum } </span>
</div>
<VoteMain supNum={supNum} oppNum={oppNum} ></VoteMain>
<VoteFooter ></VoteFooter>
</div>
}
export default Vote;
- VoteMain.jsx
import React from "react";
import ThemeContext from "../ThemeContext";
class VoteMain extends React.Component {
static contextType = ThemeContext;
render() {
const {store} = this.context;
const { supNum, oppNum } = store.getState();
let ratio = "--";
let total = supNum + oppNum;
if (total > 0) {
ratio = (supNum / total).toFixed(2);
}
return <div className="main">
<p>支持人数:{ supNum }</p>
<p>反对人数:{ oppNum }</p>
<p>支持比率:{ ratio }</p>
</div>
}
componentDidMount() {
const { store } = this.context;
store.subscribe( () => {
this.forceUpdate();
});
}
}
export default VoteMain;
- VoteFooter.jsx
import React, { useContext } from "react";
import { Button } from "antd"
import ThemeContext from "../ThemeContext";
function VoteFooter() {
const { store } = useContext(ThemeContext);
return <div className="footer">
<Button onClick={ () => {
store.dispatch({
type: "VOTE_SUP"
})
}} type="primary">支持</Button>
<Button onClick={() => {
store.dispatch({
type: "VOTE_OPP"
})
}} type="primary" danger>反对</Button>
</div>
}
export default VoteFooter;
类组件的更新
总结:
redux具体的代码编写顺序
1.创建store,规划出reducer r当中的业务处理逻辑可以后续不断完善,但是最开始reducer的这个架子需要先搭建取来J2.在入口中,基于上下文对象,把store放入到上下文中;需要用到store的组件,从上下文中获取!!
3.组件中基于store,完成公共状态的获取、和任务的派发
+使用到公共状态的组件,必须向store的事件池中加入让组件更新的办法,只有这样,才可以确保,公共状态改变,可以让组件更新,才可以获取最新的状态进行绑定!!