Redux学习总结一

参考阮一峰博客:redux教程

一、react设计思想

  1. web应用是一个状态机,视图与状态是一一对应的。
  2. 所有状态都保存在一个对象里面。

二、redux基本概念

1. Store

Store是保存数据的地方,可以将其看成一个容器,整个应用只能有一个Store.

2. State

State是Store对象的某个时点的数据集合,当前时刻的State可以通过store.getState()得到。

3. Action

State和View一一对应,Action就是View发出的通知,表示State应该要发生变化了。
Action是一个对象,其中的type属性是必须的,表示Action的名称。

注:改变State的唯一办法就是使用Action.

4. Action Creator

它是用以定义一个函数来生成Action

const ADD_TODO = '添加 TODO';
function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}
const action = addTodo('Learn Redux');

5. store.dispatch()

它是View发出Action的唯一方法,接受一个Action对象作为参数并将它发送出去。

import { createStore } from 'redux';
const store = createStore(fn);
store.dispatch({
  type: 'ADD_TODO',
  payload: 'Learn Redux'
});

6. Reducer

Reducer是一个函数,它接受Action和当前State作为参数,返回一个新的State.

const defaultState = 0;
const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case 'ADD':
      return state + action.payload;
    default: 
      return state;
  }
};
const state = reducer(1, {
  type: 'ADD',
  payload: 2
});

注:实际应用中,store.dispatch方法会触发Reducer的自动执行,因此createStore可接受Reducer作为参数生成一个新的Store.

7. 纯函数

Reducer函数最重要的特征是一个纯函数,即同样的输入必定得到同样的输出。
纯函数是函数式编程的概念,必须遵守以下约束:

1. 不得改写参数
2. 不能调用系统I/O的API
3. 不能调用Date.now()或者Math.random()等不纯的方法,因为每次都会得到不一样的结果

注:Reducer函数里面不能改变State,必须返回一个全新的对象。

// State 是一个对象
function reducer(state, action) {
  return Object.assign({}, state, { thingToChange });
  // 或者
  return { ...state, ...newState };
}
// State 是一个数组
function reducer(state, action) {
  return [...state, newItem];
}

8. store.subscribe()

Store允许使用store.subscribe方法设置监听函数,一旦State发生变化,就自动执行这个函数。

//将View的更新函数放入listen可以实现View的自动渲染
import { createStore } from 'redux';
const store = createStore(reducer);
store.subscribe(listener);
//store.subscribe方法返回一个函数,调用这个函数就可以解除当前listener监听
let unsubscribe = store.subscribe(() =>
  console.log(store.getState())
);
unsubscribe();

三、Store的实现

store提供了三个方法:store.getState()/store.dispatch()/store.subscribe()

import { createStore } from 'redux';
let { subscribe, dispatch, getState } = createStore(reducer);

注:createStore方法还接受第二个参数,表示state的最初状态,它会覆盖Reducer函数的默认初始值。

//createStore方法的简单实现
const createStore = (reducer) => {
  let state;
  let listeners = [];
  const getState = () => state;
  const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
  };
  const subscribe = (listener) => {
    listeners.push(listener);
    return () => {
      listeners = listeners.filter(l => l !== listener);
    }
  };
  dispatch({});
  return { getState, dispatch, subscribe };
};

四、 Reducer的拆分

Redux提供了一个combineReducers方法用于Reducer的拆分。

import { combineReducers } from 'redux';

const chatReducer = combineReducers({
  chatLog,
  statusMessage,
  userName
})
export default todoApp;

注:state属性名必须与子Reducer同名,combineReducers()函数会根据State的key去执行相应的子Reducer,并将返回结果合并成一个大的state对象。

//combineReducer的简单实现
const combineReducers = reducers => {
  return (state = {}, action) => {
    return Object.keys(reducers).reduce(
      (nextState, key) => {
        nextState[key] = reducers[key](state[key], action);
        return nextState;
      },
      {} 
    );
  };
};

五、工作流程

  1. 用户发出Action.
    store.dispatch(action);
  2. Store自动调用Reducer,且传入两个参数,当前State和收到的Action,Reducer会返回新的State.
    let nextState = todoApp(previousState, action);
  3. State一旦发生变化,Store会调用监听函数.
    store.subscribe(listener);
  4. listener通过store.getState()得到当前状态,若用react,则会触发重新渲染View.
function listerner() {
  let newState = store.getState();
  component.setState(newState);   
}

六、实例:计数器
功能:为计数器添加递增和递减的Action,并将参数value的值显示在网页上,Store的监听函数设置为render,每次State的变化都会导致网页重新渲染。

const Counter = ({ value, onIncrement, onDecrement }) => (
  <div>
  <h1>{value}</h1>
  <button onClick={onIncrement}>+</button>
  <button onClick={onDecrement}>-</button>
  </div>
);
const reducer = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT': return state + 1;
    case 'DECREMENT': return state - 1;
    default: return state;
  }
};
const store = createStore(reducer);
const render = () => {
  ReactDOM.render(
    <Counter
      value={store.getState()}
      onIncrement={() => store.dispatch({type: 'INCREMENT'})}
      onDecrement={() => store.dispatch({type: 'DECREMENT'})}
    />,
    document.getElementById('root')
  );
};
render();
store.subscribe(render);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值