Skip to content

动手实现一个redux #48

@aermin

Description

@aermin

概念

  • 一个app有一个store,一个store管理着一个全局state
  • createStore 传入reducer,返回getState, dispatch, subscribe
  • action是一个至少有type这个键的对象,可以写一个creactActioner 函数去return生成action对象
  • createStore.dispatch(action) 根据action这个对象去更新state
  • dispatch是一个函数,内部有将执行reducer函数
  • reducer也是一个函数,传入state,action, 输出一个新的state . (switch case return….)

demo链接

qq20180719-212609-hd

<div id = 'title'></div>
<input type="button" id = "changeTheme" value="变成蓝色主题">
//实现一个createStore
function createStore(reducer) { // 参数是reducer函数(纯函数)
  let state = null;
  const listeners = [];
  const subscribe = listener => listeners.push(listener); // 观察者模式,订阅一次,每次dispatch时都会执行传入的这个函数
  const getState = () => state;
  const dispatch = (action) => {
    state = reducer(state, action);
    listeners.forEach(listener => listener()); // 订阅监听函数
  };
  dispatch({}); // 初始化 state 也就是执行reducer函数,由于没传state,state被默认值替换( {themeName: 'Red Theme',themeColor: 'red'})
  return { getState, dispatch, subscribe };
}

// 写一个reducer
function themeReducer(state, action) {
  if (!state) {
    return { // 若没传state 则返回一个默认的state对象
      themeName: 'Red Theme',
      themeColor: 'red'
    };
  }
  switch (action.type) {
    case 'UPATE_THEME_NAME':
      return { ...state, themeName: action.themeName };
    case 'UPATE_THEME_COLOR':
      return { ...state, themeColor: action.themeColor };
    default:
      return state;
  }
}

// 把reducer传入createStore 生成 store`
const store = createStore(themeReducer); // 这边也初始化了state

// 渲染页面的代码
function renderApp(state) {
  const titleDOM = document.getElementById('title');
  titleDOM.innerHTML = state.themeName;
  titleDOM.style.color = state.themeColor;
}

// 监听数据变化重新渲染页面
store.subscribe(() => renderApp(store.getState()));// 让每次dispatch时都会执行传入的这个函数,渲染页面

// 首次渲染页面
renderApp(store.getState());


// 后面可以随意 dispatch  action了,页面自动更新

//creactActioner  action生成函数
const updateThemeName = () => ({
  type: 'UPATE_THEME_NAME',
  themeName: 'Blue Theme'
});
const updateThemeColor = () => ({
  type: 'UPATE_THEME_COLOR',
  themeColor: 'blue'
});

document.getElementById('changeTheme').onclick = () => {
  store.dispatch(updateThemeName());
  store.dispatch(updateThemeColor());
  //这样也行
  //store.dispatch({ type: 'UPATE_THEME_NAME', themeName: 'Blue Theme' });
  //store.dispatch({ type: 'UPATE_THEME_COLOR', themeColor: 'blue' });
};

参考:react小书

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions