Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

手动写一个redux中的createStore #10

Open
RachelRen opened this issue Aug 5, 2018 · 0 comments
Open

手动写一个redux中的createStore #10

RachelRen opened this issue Aug 5, 2018 · 0 comments

Comments

@RachelRen
Copy link
Owner

redux里面主要有 action, reducer, dispatch, store, 他们三个的关系是

  1. 通过dispatch触发一个action,然后把这个action和之前的state传给reducer,这样就生成了一个新的state
  2. store就是管理所有state的

rudux的特点是:

  1. 单一数据源(store)
  2. 修改状态使用纯函数来实现的(reducer)
  3. 状态只读(getState)

Redux 三大核心

  1. Store: 是个对象,贯穿整个应用的数据都存储在这里
  2. Action: 是个对象,必须包含type这个属性,reducer将根据这个属性值来对store进行相应的处理。除此之外的属性,就是进行这个操作需要的数据
  3. Reducer: 是个函数。接受两个参数: 要修改的数据(state)和action对象。根据action.type来决定采用的操作,对state进行修改,最后返回新的state

##Redux核心之间的关系

触发action -> reducer来处理。 这两者之间的关系,怎么来触发action呢?

Store这个对象提供了dispatch方法 -> 触发action。 dispatch方法接受action对象作为参数。

`store` ➡️ `dispatch` ➡️ `action` ⬅️ `reducer`

所以手写redux的关键就是

  1. 创建一个store,他是管理所有数据源的
  2. reducer其实是一个类似callback的函数,所以需要决定在什么时候去触发这个reducer,以及触发完之后,怎么改变这个store
  3. redux是主要运用了观察者模式,所以怎么去监听观察者也是一个问题
  4. dispatch方法里面运行什么

所以大致的逻辑如下:

function createStore(reducer){
  let state;
  const listeners = [];
  const subscribe = (listener) => listeners.push(listener);
  const dispatch = (action) => {
    state = reducer(state, action)
    listeners.forEach((listener) => listener())
  };

  const getState = () => state;

  dispatch({})
  return {dispatch, getState, subscribe}
}

这个store的提供的方法主要是:

  1. getState
  2. dispatch
  3. subscribe

实际应用如下:

const store = createStore(reducer)
let oldState = store.getState();
store.subscribe(() => {
  const newState = store.getState()
  renderApp(newState, oldState)
  oldState = newState;
})

renderApp(store.getState())
store.dispatch({ type: '', text: 'xxx' }) 

这只是一个很简单的例子,没有像reducer里面的applyMiddleware,combineReducers,bindActionCreators这些方法。

完成及调用方法如下:

let appState = {
  title: {
    text: 'text title',
    color: 'red',
  },
  content: {
    text: 'text content',
    color: 'blue'
  }
}
// reducer
function stateChanger (state=appState, action) {
  
  switch (action.type) {
    case 'UPDATE_TITLE_TEXT':
    return { // 构建新的对象并且返回
        ...state,
        title: {
          ...state.title,
          text: action.text
        }
      }
      // state.title.text = action.text
      break
    case 'UPDATE_TITLE_COLOR':
      return { // 构建新的对象并且返回
        ...state,
        title: {
          ...state.title,
          color: action.color
        }
      }
      //state.title.color = action.color
      break
    default:
      return state
      break
  }
}

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
  }
}


function renderApp (newAppState, oldAppState = {}) {
  
  if (newAppState === oldAppState) return 
  console.log('render app...')
  renderTitle(newAppState.title, oldAppState.title )
  renderContent(newAppState.content, oldAppState.content)
}

function renderTitle (newTitle, oldTitle = {}) {
  if (newTitle === oldTitle) return 
  console.log('render title...')
  const titleDOM = document.getElementById('title')
  titleDOM.innerHTML = newTitle.text
  titleDOM.style.color = newTitle.color
}

function renderContent (newContent, oldContent) {
  if (newContent === oldContent) return 
  console.log('render content...')
  const contentDOM = document.getElementById('content')
  contentDOM.innerHTML = newContent.text
  contentDOM.style.color = newContent.color
}

//renderApp(appState) // 首次渲染页面
//dispatch({ type: 'UPDATE_TITLE_TEXT', text: '《React.js 小书》' }) // 修改标题文本
//dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) // 修改标题颜色
//renderApp(appState) // 把新的数据渲染到页面上


function createStore(reducer){
  let state;
  const listeners = [];
  const subscribe = (listener) => listeners.push(listener);
  const dispatch = (action) => {
    state = reducer(state, action)
    listeners.forEach((listener) => listener())
  };

  const getState = () => state;

  dispatch({})
  return {dispatch, getState, subscribe}
}


const store = createStore(stateChanger)
let oldState = store.getState();
store.subscribe(() => {
  const newState = store.getState()
  renderApp(newState, oldState)
  oldState = newState;
})

//const newState = store.getState();

renderApp(store.getState())
store.dispatch({ type: 'UPDATE_TITLE_TEXT', text: 'tex1' }) 
store.dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) 

真实的redux的流程:

  • Redux: store, action, reducer

    • store: getState, dispatch, subscribe
    • combineReducers
    • createStore
    • store ➡️ dispatch ➡️ action ⬅️ reducer

动手实现 Redux
Redux 关系图解

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant