Redux必知一

243 阅读3分钟

JavaScript纯函数

函数式编程中有一个重要的概念叫纯函数,JavaScript符合函数式编程的范式。所以也有纯函数的概念。

什么是纯函数呢?

在程序设计中,一个函数符合以下条件,那么这个函数被称为纯函数:

  • 确定的输入,一定产生确定的输出;
  • 函数在执行过程中,不能产生副作用;(副作用:不能随便的修改外界的东西,当调用函数时,被调用函数除了返回函数值之外,还对主调用函数产生附加的影响。)

纯函数给我们带来什么好处呢?:不用考虑函数对外界值的修改,值关注核心的业务逻辑即可。

React非常灵活,但它有一个严格的规则:所有React组件都必须像纯函数一样保护它们的props不被更改,并且Redux也被要求是一个纯函数

为什么需要Redux?

随着目前开发JavaScript需要管理的状态越来越多,越来越复杂。包括很多的数据、缓存、用户操作产生的数据。因此我们需要一个容器,方便我们管理各种状态。而Redux就是一个帮助我们管理状态的容器:Redux是JavaScript的状态容器,提供了可预测的状态管理,使我们在管理状态的时候方便追踪

Redux的核心理念

  • Store(仓库):存储状态的地方
  • action:是一个对象,规定了数据如何变化,仓库中所有的数据变化都要通过派发action来更新
  • reducer:是一个纯函数,用于联系action的对象和Store仓库来操作State

Redux的三大原则:

  • 单一数据源,整个应用程序只有一个store
  • State是只读的,唯一修改State的方式就是触发action
  • 必须使用纯函数来执行修改

Redux的基本使用:

redux是可以脱离React进行单独使用的,也就是说你可以再js,vue甚至angular中使用: 下述演示案例是再node中用js文件的方式使用

//基本用法
//1.导入redux,node中通过es6导入部分版本不支持,故使用CommonJS的方式进行导入
const redux = require('redux');

const initialState = {
    counter: 0,

}

//reducer
let reducer = function( state = initialState, action) {
    switch(action.type) {
        case 'INCREMENT':
            return {...state, counter:state.counter + 1}
        case "DECREMENT":
            return {...state, counter:state.counter - 1}
        case "ADD_NUMBER":
            return {...state, counter:state.counter + action.num}
        case "SUB_NUMBER":
            return {...state, counter:state.counter - action.num}
        default:
            return state
    }
}

//store
const store = redux.createStore(reducer)

//actions
const action1 = { type:"INCREMENT" };
const action2 = { type:"DECREMENT" };
const action3 = { type:"ADD_NUMBER" , num:5 }
const action4 = { type:"SUB_NUMBER" , num:12 }

//订阅store修改
store.subscribe(()=>{
    console.log('counter:',store.getState().counter);
})

//派发
store.dispatch(action1)
store.dispatch(action2)
store.dispatch(action2)
store.dispatch(action3)
store.dispatch(action4)

在真实开发中如何组织store文件夹

./index.js

import store from './store/index.js'
import { addAction,subAction } from './store/actionCreator.js'

store.subscribe(() => {
    console.log(store.getState());
})

store.dispatch(addAction(10))
store.dispatch(subAction(5))

./store/index.js

import redux from 'redux'
import reducer from './reducer.js'

const store = redux.createStore(reducer)

export default store;

./store/actionCreator.js

import {
    ADD_NUMBER,
    SUB_NUMBER
} from './constant.js'

export const addAction = (num) => {
    return {
        type:ADD_NUMBER,
        num
    }
}

export const subAction = (num) => {
    return {
        type:SUB_NUMBER,
        num
    }
}

./store/reducer.js

import defaultState from './state.js'
import {
    ADD_NUMBER,
    SUB_NUMBER
} from './constant.js'

export default function reducer(state = defaultState , action) {
    switch(action.type) {
        case ADD_NUMBER:
            return {...state,counter:state.counter + action.num}
        case SUB_NUMBER:
            return {...state,counter:state.counter - action.num}
        default:
            return state
    }
}

./store/constant.js

export const ADD_NUMBER = 'ADD_NUMBER';
export const SUB_NUMBER = 'SUB_NUMBER';

./store/state.js

const defaultState = {
    counter:0
}

export default defaultState