REDUX
REACT-REDUX
* REACT-REDUX是把REDUX进一步封装,适配REACT项目,让REDUX操作更简洁
* STORE文件夹中的内容和REDUX一模一样
* 在组件调取使用的时候可以优化一些步骤
*
* 1.Provider 根组件
* 当前整个项目都在Provider组件下,用Provider包起来
* 作用就是把创建的STORE可以供内部任何后代组件使用(基于上下文完成的)
*
* =>Provider组件中只允许出现一个子元素
* =>把创建的STORE基于属性传递给Provider(这样后代组件中都可以使用这个STORE了)
render(<Provider store={store}> <section className='panel panel-default' style={{width: '50%', margin: '20px auto'}}> <VoteBase/> <VoteHandle/> </section> </Provider>, root);
* 2.connect 高阶组件
* 相对于传统的REDUX,我们做的步骤优化
* import {connect} from 'react-redux'
* 1. 导出的不在是我们创建的组件,而是基于CONNECT构造后的高阶组件
* export default connect([mapStateToProps], [mapDispatchToProps])([自己创建的组件]);
//=>把REDUX容器中的状态信息遍历,赋值给当前组件的属性(state) let mapStateToProps = state => { //=>state:就是REDUX容器中的状态信息 //=>我们返回的是啥,就把它挂载到当前组件的属性上(REDUX存储很多信息,我们想用啥就 //=>返回啥即可) return { ...state.vote }; };*/ //=>把REDUX中的DISPATCH派发行为遍历,也赋值给组件的属性(ActionCreator) let mapDispatchToProps = dispatch => { //=>dispatch:STORE中存储的DISPATCH方法 //=>返回的是啥,就相当于把啥挂载到组件的属性上(一般我们挂载一些方法,这些方法中 //=>完成了DISPATCH派发任务操作) return { init(initData) { dispatch(action.vote.init(initData)); } }; }; export default connect(mapStateToProps, mapDispatchToProps)(VoteBase);
export default connect(state => ({...state.vote}), action.vote)(VoteBase); //=>REACT-REDUX帮我们做了一件事情,把ACTION-CREATOR中编写的方法(返回ACTION对象 //=>的方法),自动构建成DISPATCH派发任务的方法,也就是mapDispatchToProps这种格式
* 2. REACT-REDUX帮我们做了一件非常重要的事情:以前我们需要自己基于SUBSCRIBE向事件池追加方法,以达到容器状态信息改变,执行我们追加的方法,重新渲染组件的目的,但是现在不用了,REACT-REDUX帮我们做了这件事:“所有用到REDUX容器状态信息的组件,都会向事件池中追加一个方法,当状态信息改变,通知方法执行,把最新的状态信息作为属性传递给组件,组件的属性值改变了,组件也会重新渲染”
REDUX原理之CREATE-STORE
/*
* createStore:创建REDUX容器的
* @PARAMS
* reducer:函数
* @RETURN
* store : {
* getState,
* dispatch,
* subscribe
* }
*/
function createStore(reducer) {
//=>创建一个STORE,STATE用来存储管理的状态信息,LISTEN-ARY用来存储事件池中的方法
//=>STATE不用设置初始值,因为第一次DISPATCH执行REDUCER,STATE没有值,走的是
//=>REDUCER中赋值的默认值信息,我们自己会在创建容器的时候就把DISPATCH执行一次!
let state,
listenAry = [];
//=>DISPATCH:基于DISPATCH实现任务派发
function dispatch(action) {
//1.执行REDUCER,修改容器中的状态信息(接收REDUCER的返回值,把返回的信息替换原有的STATE),值得注意的是:我们是把返回值全部替换STATE,所有要求REDUCER中在修改状态之前,要先把原始的状态信息克隆一份,在进行单个的属性修改
state = reducer(state, action);
//2.容器中状态信息经过REDUCER修改后,通知事件池中的方法依次执行
for (let i = 0; i < listenAry.length; i++) {
let item = listenAry[i];
if (typeof item === 'function') {
item();
} else {
listenAry.splice(i, 1);
i--;
}
}
}
dispatch({type: '$$INIT_DEFAULT_STATE'});//=>创建容器的时候执行一次DISPATCH,目的是把REDUCER中的默认状态信息赋值给REDUX容器中的状态
//=>GET-STATE:获取容器中的状态信息
function getState() {
//1.我们需要保证返回的状态信息不能和容器中的STATE是同一个堆内存(否则外面获取状态信息后,直接就可以修改容器中的状态了,这不符合DISPATCH->REDUCER才能改状态的规范)
/*//[浅克隆]
AAAFFF111:{vote:BBBFFF111}
{...state} => AAAFFF222:{vote:BBBFFF111}*/
return JSON.parse(JSON.stringify(state));//=>深度克隆对象
}
//=>SUBSCRIBE:向事件池中追加方法
function subscribe(fn) {
//1.向容器中追加方法(重复验证)
let isExit = listenAry.includes(fn);
!isExit ? listenAry.push(fn) : null;
//2.返回一个方法:执行返回的方法会把当前绑定的方法在事件池中移除掉
return function unsubscribe() {
let index = listenAry.indexOf(fn);
// listenAry.splice(index, 1);//=>可能会引发数组塌陷
listenAry[index] = null;
}
}
return {
dispatch,
getState,
subscribe
};
}