再厉害的魔术也比不上真正的redux

1,969 阅读3分钟

why redux?

  • 随着 JavaScript 单页应用开发日趋复杂,管理不断变化的 state 非常困难
  • Redux的出现就是为了解决state里的数据问题
  • 在React中,数据在组件中是单向流动的
  • 数据从一个方向父组件流向子组件(通过props),由于这个特征,两个非父子关系的组件(或者称作兄弟组件)之间的通信比较麻烦

what is redux?

工作流

设计思想

  • Redux是将整个应用状态存储到到一个地方,称为store
  • store里面保存一棵状态树(state tree)
  • 组件可以派发(dispatch)行为(action)给store,而不是直接通知其它组件
  • 其它组件可以通过订阅store中的状态(state)来刷新自己的视图.

三大原则

  • 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中 State 是只读的,惟一改变 state 的方法就是触发 action,
  • action是一个用于描述已发生事件的普通对象 使用纯函数来执行修改,为了描述action如何改变state tree ,你需要编写 reducers
  • 单一数据源的设计让React的组件之间的通信更加方便,同时也便于状态的统一管理

how redux?

1.安装

npm i redux -S

2.简单例子

1.引入

import {createStore} from 'redux';
//createStore 用来创建状态仓库

2.创建state

let initState = {
    title: 'star'
}

3.创建reducer

const CHANGETITLE = 'CHANGETITLE'; //action-todos
function reducer(state= initState, action){
     switch(action.type){
         case CHANGETITLE: 
             return state.title = action.title;
     }
 }

4.创建仓库

let store = createStore(reducer);

5.触发dispatch中传入action

store.dispatch({type: CHANGETITLE, title: 'xingxing'})

完整代码

import {createStore} from 'redux';
const CHANGETITLE = 'CHANGETITLE';
function reducer(state= initState, action){
    switch(action.type){
        case CHANGETITLE: 
            state.title = action.title;
    }
    console.log(state);
}
let store = createStore(reducer);
store.subscribe(()=>{                    //订阅事件,在dispatch时触发
    console.log('render');
})
store.dispatch({type: CHANGETITLE, title: 'xingxing'})

复杂些例子

在真实开发中需要开辟一个文件空间来管理仓库

  • 文件结构化
  • 多reducer,合并reducer

1.actions

action-type.js
//action-type衡量,通过引入使用,减少拼写错误引发的问题
export const INCREMENT = 'INCREMENT'
export const DECREMNET = 'DECREMNET'
actions/count.js
import * as types from "../action-types"
//用于生成action
let counter = {
    add(n){
         return {type: types.INCREMENT, count: n}
    }
}
export default counter

2.reducers

reducers/count.js
import {INCREMENT,DECREMENT} from '../actions/action-type'
let initState = {
    count: 0
}
function reducer(state = initState,action){
    switch(action.type){
        case INCREMENT:
             state.count = state.count + action.number;
            break;
        case DECREMENT:
            state.count = state.count - action.number;
            break;
    }
    return state
}
export default reducer
合并reducer
reducers/index.js
import todos from './todo';
import count from './count';
import {combineReducers} from 'redux'
let reducers = combineReducers({
    todos,
    count
})
export default reducers;

store/index.js 初始化仓库

import {INCEMENT,DECREMENT} from './actions/action-type';
import {createStore} from 'redux';
import reducers from './reducers'

export default createStore(reducers);

how is redux work?

  • redux的数据源是创建reducer时,传进去的initState。
  • 为了避免state被随意篡改,redux通过dispatch reducer来更改数据。
  • redux可以通过subscribe订阅状态修改事件
//简单实现
function createStore(reducer){
    let state;
    let listeners = [];
    function subscribe(listener){
        listeners.push(listener);
        return ()=> listeners = listeners.filter(fn=>fn!==listener);
    }
    function dispatch(action){
        listeners.forEach(listener=>listener());
        reducer(state, action)
    }
    dispatch({})
    function getState(){
        return state;
    }
    return {subscribe, dispatch, getState}
}

合并reducer

function combineReducers(reducers){
    return (state={},action)=>{
        let newState = {};
        for(let key in reducers){
            let s = reducers[key](state[key],action);
            newState[key] = s;
        }
        return newState;
    }
}

完整代码

function createStore(reducer){
    let state;
    let listeners = [];

    function subscribe(listener){
        listeners.push(listener);
        return ()=>{
            listeners = listeners.filter(l=> l!==listener)
        }
    }
    dispatch({})
    function dispatch(action){
        state = reducer(state,action);
        listeners.forEach(l=>l());
    }
    function getState(){
        return state;
    }
    return {subscribe,dispatch,getState};
}

function combineReducers(reducers){
    return (state={},action)=>{
        let newState = {};
        for(let key in reducers){
            let s = reducers[key](state[key],action);  
            newState[key] = s;
        }
        return newState;
    }
}

export {createStore,combineReducers}

最近在研究redux,欢迎指出问题。后续更新react-redux全家桶系列研究