Redux step by step to achieve one of their own

Said front

In order to learn redux, to achieve a just store, createStore, reducerand some other basic functions


Now forget everything

First create a new project with the create-react-app, modify the public/index.htmlstructure of the page under

  <body>
    <div id='title'></div> <div id='content'></div> </body> 

Empty srcfolder, create a new index.js, add code that represents the state we want to apply:

const appState = {
  title: {
    text: 'Redux',
    color: 'red', }, content: { text: '学习redux', color: 'blue' } } 

Add the rendering function, will render the above status data to the page:

function renderApp (appState) {
  renderTitle(appState.title)
  renderContent(appState.content)
}

function renderTitle (title) { const titleDOM = document.getElementById('title') titleDOM.innerHTML = title.text titleDOM.style.color = title.color } function renderContent (content) { const contentDOM = document.getElementById('content') contentDOM.innerHTML = content.text contentDOM.style.color = content.color } 

Simple rendering is complete, but there will be a serious problem, rendering the data using a shared state appState, anyone can modify , if we do operate other functions before rendering it unable to Chile Big East will appStatedo what things, is why to avoid global variables

Between the different components when we need to share data, it is a contradiction:

❗❗ data shared data may be arbitrarily modified within the assembly between the components

If we learn about React team approach, the operation becomes complicated

Can be shared between components, but can not directly modify the data changes, you must perform some of the functions defined in I

Define a dispatchfunction that is responsible for data modification

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

We operate on the data must pass through dispatchfunction that takes one argument action, which is a normal object, which contains a typefield to the life you want to do, dispatchwithin switchrecognizes this field, identify successful will appStatebe modified

The above dispatchit can identify only two operations, one is UPDATE_TITLE_TEXTthat it will use actionthe textfields to update appState.title.text; one is UPDATE_TITLE_COLOR, it will use actionthe colorfields to update appState.title.color. actionWhich in addition to typefield is required, other fields are customizable.

If you want to modify appState.title.text, you must calldispatch

dispatch({ type: 'UPDATE_TITLE_TEXT', text: 'React.js' }) // 修改标题文本 dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) // 修改标题颜色 

So do not worry about the other functions will modify appState, at least directly modify

original:

Now all the data you want to modify must dispatch:


Pulled outstore

Now, with appStateand dispatch, we can put them together in one place, named called store, and then build a createStore()function, used to produce this stateand dispatchcollections

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

createStoreTakes two parameters, a state is represented state, the other is stateChanger, it is used to describe the state of the application based on actionwhat happens, equivalentdispatch

createStoreReturns an object that contains two methods getStatefor acquiring statethe data, dispatchmodify the data, and as before

Now my code can be optimized to:

et appState = {
  title: {
    text: 'React.js',
    color: 'red', }, content: { text: 'React.js 内容', color: 'blue' } } function stateChanger (state, action) { switch (action.type) { case 'UPDATE_TITLE_TEXT': state.title.text = action.text break case 'UPDATE_TITLE_COLOR': state.title.color = action.color break default: break } } const store = createStore(appState, stateChanger) renderApp(store.getState()) // 首次渲染页面 store.dispatch({ type: 'UPDATE_TITLE_TEXT', text: 'React.js' }) // 修改标题文本 store.dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) // 修改标题颜色 renderApp(store.getState()) // 把新的数据渲染到页面上 

Then we have a difficult problem, how to monitor data changes, the above code, if we do not call renderApp, the content of that page is not going to change, if to dispatchadd renderApp, that we want universal createStoredie, would like to use a species common way monitor data, need to use the observer pattern:

function createStore (state, stateChanger) {
  const listeners = [] const subscribe = (listener) => listeners.push(listener) const getState = () => state const dispatch = (action) => { stateChanger(state, action) listeners.forEach((listener) => listener()) } return { getState, dispatch, subscribe } } 

在方法中定义了一个数组,还有一个subscribe方法,可以通过这个方法传入一个监听函数,并push到数组中,修改了dispatch方法,当它被调用的时候,会遍历数组中的函数,一个个的调用,这就意味着我们可以通过subscribe传入数据变化的监听函数,每次dispatch的时候,监听函数都会被调用

const store = createStore(appState, stateChanger)
store.subscribe(() => renderApp(store.getState()))

renderApp(store.getState()) // 首次渲染页面
store.dispatch({ type: 'UPDATE_TITLE_TEXT', text: 'React.js' }) // 修改标题文本 store.dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) // 修改标题颜色 // ...后面不管如何 store.dispatch,都不需要重新调用 renderApp 

只需要subscribe一次,后面不管怎么dispatchrenderApp都会被重新调用,重新渲染页面,而且观察者模式下同一块数据也可以渲染其他页面。

阶段总结

现在有了通用的createStore,可以产生一种新定义的数据类型store,通过getState获取状态,dispatch修改状态,subscribe监听数据……

Guess you like

Origin www.cnblogs.com/moe0321/p/12334733.html