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自己是一個函數,傳遞兩個參數,分別爲state和action,而後判斷action.type來進行不一樣的邏輯來改變statereact
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;
複製代碼
用來合併多個reducerredux
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就是一個包括type和payload屬性的對象數組
export default {
add(val){
return {type:Types.INCREMENT,count:val}
}
}
複製代碼
將action包裝成自動dispatchbash
let bindActionCreators = (actions,dispatch) => {
let obj = {}
for(let key in actions){
obj[key] = (...args) => dispatch(actions[key](...args))
}
return obj;
}
複製代碼
用來鏈接react和redux的ide
ReactDOM.render(<Provider store={store}>
<>
<Counter></Counter>
</>
</Provider>,window.root);
複製代碼
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>)
}
}
複製代碼
第一次執行傳遞兩個參數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)
複製代碼
context API + 高階組件ui
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;
複製代碼