redux/createStore方法返回getState、dispatch和subscribe。
- 组件之间通过调用dispatch action,action传入到reducer中,然后根据老的state和action生成新的状态。监听渲染函数数组遍历执行
- getState返回当前状态state
- subscribe函数调用将渲染函数暂存到一个数组中,并返回一个函数用来过滤掉当前绑定函数,也就是取消订阅。
function createStore(reducer){
let state;
getState = () => state;
let listeners = [];
let dispatch = function(action){
state = reducer(state,action);
listeners.forEach(fn=>fn())
}
<!--默认状态state-->
dispatch({type:'@INIT'})
let subscribe = function(fn){
listeners.push(fn);
return function(){
listeners = listeners.filter(l=>l!=fn)
}
}
return {
getState,
subscribe,
dispatch
}
}
复制代码
reducer
reducer本身是一个函数,传递两个参数,分别为state和action,然后判断action.type来进行不同的逻辑来改变state
import * as Types from '../action-types'
function counter(state = {number:0},action){
switch(action.type){
case Types.INCREMENT:
return {number:state.number+ action.count}
}
return state;
}
export default counter;
复制代码
redux/combineReducers
用来合并多个reducer
function combineReducers(reducers){
return function(state={},action){
let obj = {};
for (let key in reducers) {
<!--第一次进来注意state[key]为undefined-->
obj[key] = reducers[key](state[key], action);
}
return obj
}
}
export default combineReducers({
counter: counter,
todo
});
复制代码
action
action就是一个包括type和payload属性的对象
export default {
add(val){
return {type:Types.INCREMENT,count:val}
}
}
复制代码
bindActionCreators
将action包装成自动dispatch
let bindActionCreators = (actions,dispatch) => {
let obj = {}
for(let key in actions){
obj[key] = (...args) => dispatch(actions[key](...args))
}
return obj;
}
复制代码
react-redux
用来连接react和redux的
Provider
ReactDOM.render(<Provider store={store}>
<>
<Counter></Counter>
</>
</Provider>,window.root);
复制代码
Provider的实现(主要是使用context API)
import React,{Component} from 'react';
import Context from './context';
// Provider 主要是提供store使用的
export default class Provider extends Component{
render(){
return (<Context.Provider value={{ store: this.props.store}}>
{this.props.children}
</Context.Provider>)
}
}
复制代码
connect
第一次执行传递两个参数mapStateToProps和mapDispatchToProps,两个都是一个函数分别传递state和dispatch参数,返回对象。
let mapStateToProps = (state) => { // store.getState()
return {
number: state.counter.number,
}
};
let mapDispatchToProps = (dispatch) => { // store.dipspatch
return {
add: (n) => dispatch(actions.add(n))
}
}
//如果connect 第一次执行的函数 ,如果第二个参数是对象类型 会自动内部调用bindActionCreator来实现
export default connect((state)=>state.counter,actions)(Counter)
复制代码
connect实现
context API + 高阶组件
import React from 'react';
import Context from './context';
import { bindActionCreators} from 'redux';
let connect = (mapStateToProps, mapDipsatchToProps)=> (Component)=>{
return ()=>{
class Proxy extends React.Component{
state = mapStateToProps(this.props.store.getState());
componentDidMount(){
this.unsub = this.props.store.subscribe(()=>{
this.setState(mapStateToProps(this.props.store.getState()))
})
}
componentWillUnmount(){
this.unsub();
}
render(){
let mapDispatch;
if (typeof mapDipsatchToProps === 'object'){ //如果第二个参数传递的是一个对象,把对象直接进行包装即可
mapDispatch = bindActionCreators(mapDipsatchToProps,this.props.store.dispatch);
}else{
mapDispatch = mapDipsatchToProps(this.props.store.dispatch);
}
return <Component {...this.state} {...mapDispatch}></Component>
}
}
return <Context.Consumer>
{({store})=>{
// 将状态 和dispatch 拿到执行函数 把结果对象传递给原本的component渲染
return <Proxy store={store}></Proxy>
}}
</Context.Consumer>
}
}
export default connect;
作者:折腾的小白攻城狮
链接:https://juejin.im/post/5c9ce73ae51d454cac6c6046
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。