# redux实现

在这里看源代码 (opens new window)

# store

  1. store提供数据的get钩子(store.getState),不直接提供数据的set,所以必须通过dispatch(action)来set数据。
  2. 利用观察者模式(sub/ pub)连接model和view的中间对象。view层通过调用store.dispatch方法触发reducer改变model。对应pub。model层通过调用store.subscribe注册视图更新事件(setstate),该事件会在数据改变之后被调用。对应sub。

# reducer

真正改变数据的方法。接受一个旧的state,返回一个新的state。这种改变方式也体现了redux不可变数据的思想。即一个数据产生,就不会变化,如果要改变这个数据,需要返回一个新的数据引用。

# 看一个redux例子

import { createStore } from 'redux';


function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1;
  case 'DECREMENT':
    return state - 1;
  default:
    return state;
  }
}

// 创建 Redux store 来存放应用的状态。
// API 是 { subscribe, dispatch, getState }。
let store = createStore(counter);

// 可以手动订阅更新,也可以事件绑定到视图层。
store.subscribe(() =>
  console.log(store.getState())
);

// 改变内部 state 惟一方法是 dispatch 一个 action。
// action 可以被序列化,用日记记录和储存下来,后期还可以以回放的方式执行
store.dispatch({ type: 'INCREMENT' });
// 1
store.dispatch({ type: 'INCREMENT' });
// 2
store.dispatch({ type: 'DECREMENT' });
// 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

可以看到 createStore 函数 获取一个reducer 返回一个对象,该对象有 getState,dispatch,subscribe

# redux实现

function createStore(reducer) {
    let state;
    let listeners = [];
    const getState = () => state;
    const subscribe = (ln) => {
        listeners.push(ln);
        //订阅之后,也要允许取消订阅。不能只准订,不准退~
        const unsubscribe = () => {
            listeners = listeners.filter(listener => ln !== listener);
        }
        return unsubscribe;
    };
    const dispatch = (action) => {
        //reducer(state, action) 返回一个新状态
        state = reducer(state, action);
        listeners.forEach(ln => ln());
    }
    //你要是有个 action 的 type 的值正好和 `@@redux/__INIT__${Math.random()}` 相等,我敬你是个狠人
    dispatch({ type: `@@redux/__INIT__${Math.random()}` });

    return {
        getState,
        dispatch,
        subscribe
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

从代码中我们可以看出

  • getState:返回存储的state数据

  • subscribe:将要观察的函数放入观察队列中

  • dispatch:执行reducer获取最新的state,存下来,然后遍历观察队列中的函数

一个简单版的redux完成了