开篇之前,让我们先来了解redux的思想

建议翻看 http://huziketang.com/books/r...

我这边简单做些总结

为什么要有dispatch

假设一种场景下,app里每个组件都需要拿到appState的一部分进行渲染。

但是这里存在一个风险就是,谁都可以修改appState的值,换句话说,有一天当appState变了你都不知道是谁改的,所以我们需要有一个管理员来帮我们管理我们的状态,这时候引入了dispatch函数,来专门
修改负责数据的修改。

function dispatch (action) {
  switch (action.type) {
    case 'UPDATE_TITLE_TEXT':
      appState.title.text = action.text
      break
    case 'UPDATE_TITLE_COLOR':
      appState.title.color = action.color
      break
    default:
      break
  }
}

解决问题:
既可以解决组件共享问题,同时不会有数据可以被任意修改的问题。

为什么要有createStore

现在我们有了状态,又有了dispatch,这时候我们需要一个高层管理者store,帮我们管理好他们,这样再用的时候就可以直接store.getState store.dispatch的方式获取和更改组件。

所以我们就有了createStore这个函数帮我们生成store, 然后将getState 跟 dispatch 方法export出去。

stateChanger

function createStore(state, stateChanger) {
  const getState = () => state;
  const dispatch = (action) => stateChanger(state, action)
  return {getState, dispatch}
}

createStore 接受两个参数,一个是表示app的 state;另外一个是 stateChanger,它来描述应用程序状态会根据 action 发生什么变化,其实就是相当于本节开头的 dispatch 代码里面的内容。

但是这里还有一个问题,就是数据发生改变之后,我们都需要手动在重新render一次APP,这时候就需要观察者模式,订阅数据的改变,然后自动调用renderAPP,所以我们的createStore功能又强大啦~

function createStore(state, reducer) {
  const getState = () => state;
  const listeners = [];
  const subscribe = (listener) => {
    listeners.push(listener)
  } 
  const dispatch = (action) => {
    reducer(state, action);
    // 数据已发生改变就把所有的listener跑一遍
    listeners.forEach((listener) => {
      listener()
    })
  }

  return {getState, dispatch, subscribe}
}

我们就可以这样使用

store.subscribe(() => renderApp(store.getState())) 

到这一步,一个APP就已经可以无压力的跑起来啦,最后一步,当然是关注性能,我们这个app 还是有严重性能问题的,因为每一次的dispatch 所有的子组件都会被重新渲染,这当然是不必要的。

所以就需要对reducer产生的前后appState进行一个对比,这就要求reducer必须是一个纯函数,这样才能够对比可以通过对比前后的state是否相等,来决定是否render,然后在subscrible 里加两行代码。

// reducer用来管理状态变化
function reducer (state, action) {
  if(!state) {
    return appState;
  }
  switch (action.type) {
    case 'CHANGE_TITLE':
      return {
        ...state,
        title: {
          ...state.title,
          text: action.text
        }
      }
    case 'CHANGE_CONTENT':
      return {
        ...state,
        content: {
          ...state.content,
          color: action.color
        }
      }
  }
}
function createStore(state, reducer) {
  let appState = state;
  const getState = () => appState;
  const listeners = [];
  const subscribe = (listener) => {
    listeners.push(listener)
  } 
  const dispatch = (action) => {
    // 覆盖原先的appState
    appState = reducer(state, action);
    listeners.forEach((listener) => {
      listener()
    })
  }

  return {getState, dispatch, subscribe}
}

OK,到这一步,我们的redux就基本完成啦~ 接着改装下我们的reducer,让它有一个初始值,这样我们的createStore就只需要传入一个reducer即可

function createStore (reducer) {
  let state = null
  const listeners = []
  const subscribe = (listener) => listeners.push(listener)
  const getState = () => state
  const dispatch = (action) => {
    state = reducer(state, action)
    listeners.forEach((listener) => listener())
  }
  dispatch({}) // 初始化 state
  return { getState, dispatch, subscribe }
}

总结以下:createStore里要做三件事

  • getState
  • dispatch
  • subscribe
  • 初始reducer的状态

四个步骤

// 定一个 reducer, 负责管理数据变化还有初始化appState的数据
function reducer (state, action) {
  /* 初始化 state 和 switch case */
}

// 生成 store
const store = createStore(reducer)

// 监听数据变化重新渲染页面
store.subscribe(() => renderApp(store.getState()))

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

// 后面可以随意 dispatch 了,页面自动更新
store.dispatch(...)

我们整个过程就是不断地发现问题,解决问题

1、共享状态 -> dispatch
2、store统一管理 dispatch getState
3、性能优化 --> dispatch是一个纯函数
4、最终初始化整个reducer

以上就是redux的大致思想。


幽_月
316 声望72 粉丝

引用和评论

0 条评论