5. redux

186 阅读3分钟

1.一张图了解redux

  • createStore(【reducer管理员】,【preloadedstate初始状态】)
  • reducer函数=>根据不同的type标识,修改不同信息
  • store.getState()
  • store.subscribe([方法])
  • store.dispatch({type:xxx,xxx:xxx})

1.从STORE容器中获取最新的状态信息,展示在页面中=>先把STORE容器中的状态赋值给私有状态

2.把某个方法增加到STORE的事件池中;当STORE容器中的状态改变,通知此方法执行,此方法可以把当前组件重新渲染;

=> 方法中获取最新的STORE容器中的状态,基于SETSTATE方法控制视图的重新渲染;

应用

    1. 引入 createStore => import { createStore } from 'redux';
    1. 创建容器 const store = createStore(reducer,preloadState); preloadState:初始状态值
    1. 写好reducer 函数function (state = {n: 0,m: 0}, action) state:现在STORE容器中的状态信息 action:DISPATCH派发的行为对象(必然有一个TYPE行为标识) 在reducer第一次执行的时候,容器中状态没有,我们设置初始值(我们一般在reducer中设置,而不是在createStore的preloadState中设置,这样可以设置每个模块的初始状态)
import { createStore } from 'redux';

const reducer = function (state = {
	supNum: 0,
	oppNum: 0
}, action) {
	// 为了防止现在的操作和之前的STATE用同一个堆,我们把STATE最好克隆一份再操作
	state = JSON.parse(JSON.stringify(state));
	let n = action.n || 1;
	switch (action.type) {
		case 'CHANGE_SUP':
			state.supNum += n;
			break;
		case 'CHANGE_OPP':
			state.oppNum += n;
			break;
	}
	return state;
};
const store = createStore(reducer);

ReactDOM.render(<>
	<Vote store={store} />
</>, document.getElementById('root'));

组件

import React from 'react';

function VoteContent(props) {
	// 把redux中的状态赋值给组件的私有状态
	let store = props.store,
		{ supNum, oppNum } = store.getState();
	return <>
		<p>支持能:{supNum}</p>
		<p>支持不能:{oppNum}</p>
	</>;
}

function VoteButton(props) {
	let store = props.store;
	return <>
		<button onClick={ev => {
			store.dispatch({
				type: 'CHANGE_SUP',
				n: 10
			});
		}}>能</button>
		<button onClick={ev => {
			store.dispatch({
				type: 'CHANGE_OPP'
			});
		}}>不能</button>
	</>;
}

class Vote extends React.Component {
	/*
	 * 获取REDUX中的状态信息 GET-STATE
	 * 向REDUX事件池中追加方法(目的:容器中状态改变,执行这个方法,控制当前组件重新渲染)SUB-SCRIBE
	 */
	render() {
		let store = this.props.store,
			{ supNum, oppNum } = store.getState();
		return <div>
			<h3>今天天气真好 <span>N:{supNum + oppNum}</span></h3>
			<VoteContent store={store} />
			<VoteButton store={store} />
		</div>;
	}
	componentDidMount() {
		// subscribe的返回值是才事件池中移除方法的函数:unsubscribe()
		let unsubscribe = this.props.store.subscribe(() => {
			this.forceUpdate();
		});
	}
}

2.redux的工程化开发

项目构建框架

|-src

|-api
|-assets 静态资源
|-conmponents  公共组件
|-pages  各个页面
|-routes  路由
*|-store  公共管理状态
    *|-reducer
	|-voteReducer.js vote板块的reducer
        |-personalReducer.js 个人中心板块的reducer
        |-index.js  把每一个模块的reducer进行合并
    *|-action 把dispatch派发时需要的action对象管理起来
	|-voteAction.js vote板块的action对象管理
	|-index.js  合并后的action
    *|-index.js** 创建STORE
    *|-action-types.js** 派发行为类型的宏观管理
*|-index.js 入口

演示

  • store/index.js
import {
	createStore
} from 'redux';
import reducer from './reducer/index';

const store = createStore(reducer);
export default store;
  • 每个REDUCER都管理自己单独的状态(示例)
import * as TYPES from '../action-types';
const initialState = {
	supNum: 10,
	oppNum: 5
};
export default function voteReducer(state = initialState, action) {
	state = JSON.parse(JSON.stringify(state));
	switch (action.type) {
		case TYPES.VOTE_CHANGE_SUPNUM:
			state.supNum++;
			break;
		case TYPES.VOTE_CHANGE_OPPNUM:
			state.oppNum++;
			break;
	}
	return state;
};
  • 合并reducer
import {combineReducers} from 'redux';
import voteReducer from './voteReducer';
import personalReducer from './personalReducer';

export default combineReducers({
	vote: voteReducer,
	personal: personalReducer
});
  • combineReducers处理后的结果:按照模块划分状态
{
	vote: {
		supNum: 10,
		oppNum: 5,
	},
	personal: {
		supNum: 0,
		info: {}
	}
}
store.getState().vote.supNum 
  • 每个ACTION也是单独的(示例)
import * as TYPES from '../action-types';
export default {
	changeSupNum() {
		return {
			type: TYPES.VOTE_CHANGE_SUPNUM
		};
	},
	changeOppNum() {
		return {
			type: TYPES.VOTE_CHANGE_OPPNUM
		};
	}
};

合并action

import voteAction from './voteAction';
import personalAction from './personalAction';

export default {
	vote: voteAction,
	personal: personalAction
};

小小应用

//=>index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Vote from './Vote';
import store from './store/index';
ReactDOM.render(<>
	<Vote store={store} />
</>, document.getElementById('root'));

//======> vote.jsx
import React from 'react';
import actions from './store/actions/index';

function VoteContent(props) {
	let { supNum, oppNum } = props.store.getState().vote;
	return <>
		<p>支持能:{supNum}</p>
		<p>支持不能:{oppNum}</p>
	</>;
}

function VoteButton(props) {
	let store = props.store;
	return <>
		<button onClick={ev => {
			store.dispatch(actions.vote.changeSupNum());
		}}>能</button>
		<button onClick={ev => {
			store.dispatch(actions.vote.changeOppNum());
		}}>不能</button>
	</>;
}


class Vote extends React.Component {
	constructor(props) {
		super(props);
		// 把REDUX容器中的公共状态赋值给自己的私有状态
		let { vote: { supNum, oppNum } } = this.props.store.getState();
		this.state = {
			supNum,
			oppNum
		};
	}
	render() {
		let { supNum, oppNum } = this.state,
			store = this.props.store;
		return <div>
			<h3>今天天气真好! <span>N:{supNum + oppNum}</span></h3>
			<VoteContent store={store} />
			<VoteButton store={store} />
		</div>;
	}
	// 第一次渲染完,把REDUX状态改变后重新渲染组件的方法增加到事件池中
	componentDidMount() {
		this.props.store.subscribe(() => {
			this.setState({
				...this.props.store.getState().vote
			});
		});
	}
}

export default Vote;