从redux到react-redux

 

原生手写redux实现原理


import React,{Component} from 'react'

import ReactDOM from 'react-dom'
let initState=0;

let createStore=function(reducer){
    let state;
    let listeners=[];
    let getState=()=>state;
    let dispatch=(action)=>{
       state= reducer(state,action);
        listeners.forEach(item=>item())
    }
    let subscribe=(listener)=>{
        listeners.push(listener);

    }
    dispatch({})

    return {
        getState,
        dispatch,
        subscribe
    }
}
const ADD='ADD';
const SUB='SUB';

let reducer=(state=initState,action)=>{
    switch(action.type){
        case ADD:
            return state+1;break;
        case SUB:
            return state-1;break;
        default:return state;break;
    }
}
let store=createStore(reducer)
store.dispatch({type:ADD})
console.log(store.getState())
store.dispatch({type:ADD})
console.log(store.getState())
store.dispatch({type:ADD})
console.log(store.getState())

ReactDOM.render(<div></div>,document.querySelector('#root'))

 

个人理解:

事件发送方触发事件store.dispatch(传递action对象)

  store内部会根据reducer函数:state+action=新的state,可通过store.getState()获得新的state

  激发事件订阅方所注册的监听函数的执行 store.subscribe(注册监听函数)

reducer函数接收state和action两个参数

 

 

redux插件写法

npm install redux

todolist demo:

import React,{Component} from 'react'

import {createStore} from 'redux'

let initState={
    todos:[]
}
const ADD_TODO='ADD_TODO'
const DEL_TODO='DEL_TODO'
let reducer=(state=initState,action)=>{
    switch(action.type){
        case ADD_TODO:return {todos:[...state.todos,action.payload]}
        case DEL_TODO:return {todos:state.todos.filter((item,index)=>index!=action.index)};
        default:return state;
    }
}

let store=createStore(reducer)
export default class Todos extends Component{
    constructor(){
        super();
        this.state={
            todos:store.getState().todos
        }

    }
    componentDidMount(){
        this.unSubscribe=store.subscribe(()=>{
            this.setState(store.getState())
        })
    }
    componentWillUnmount(){
        this.unSubscribe();//组件卸载时 取消监听
    }
    add=(e)=>{
        if(e.keyCode==13){
            store.dispatch({type:ADD_TODO,payload:e.target.value})
            e.target.value=''
        }
    }
    render(){
        return (
            <div>
                <input type="text" onKeyDown={this.add}/>
                <ul>
                    {
                        this.state.todos.map((item,index)=>{
                            return <li key={index}>{item}<button onClick={()=>{store.dispatch({type:DEL_TODO,index:index})}}>删除</button></li>
                        })
                    }
                </ul>
            </div>
        )
    }
}

 

react-redux

npm install react-redux

目录结构

reducers目录下存放各个组件的reducer函数,index.js负责合并各个reducer ,

  使用import {combineReducers} from 'redux';

  export default combineReducers({})导出合并后的reducer

 

action-types.js存放事件类型变量名

actions.js存放函数集合的对象,每个函数返回action对象

index.js生成store,import {createStore} from 'redux';

  let store=createStore(参数是合并后的reducer)

 

在需要用store的公共父组件里

  import {Provider} from 'react-redux'  //react为redux提供的插件

  <Provider store={store}><父组件/></Provider>

那么下面的所有子组件都能连接到store

  import {connect} from 'react-redux'  //react为redux提供的插件

  import 只需引用该组件的actions对象

  导出经connect(mapStateToProps,mapDispatchToProps)(组件)更改的新的组件

    mapStateToProps(state){返回store里的state对象}//state是所有组件状态集合

    mapDispatchToProps(dispatch){返回key值是actions.js里的函数名,value值是dispatch包裹的action对象}

      可使用import {bindActionCreators} from 'redux'

      bindActionCreators(参数一:actions.js存放函数集合的对象,参数二:store的dispatch)生成所需value

        另外 connect函数的第二个可以不用手工生成,直接写actions.js存放函数集合的对象,会自动生成所需value

 

那么子组件就可以使用this.props获取store里的状态和dispatch事件了

 

 

redux演变史

 详见个人github上的demo

https://github.com/xueln/demo/tree/master/react/my-app/src

posted @ 2017-11-11 14:08  catalinaScript  阅读(115)  评论(0编辑  收藏  举报