5

whay write this: 很多小白在看过很多教程之后仍然在敲代码的时候不清楚应该以什么样的步骤进行,那么这篇文章就一步一步分解整个过程,慢动作回放让大家看的清清楚楚明明白白。

这个小Demo的功能是在input标签中输入内容,同步显示在上方的p标签内,DEMO很简单,大神们轻喷~?

项目代码在这里https://github.com/oliyg/redu...

clone: https://github.com/oliyg/redu...

废话不多说

首先上图:

/*
                 _________               ____________               ___________
                |         |             |            |             |           |
                | Action  |------------▶| Dispatcher |------------▶| callbacks |
                |_________|             |____________|             |___________|
                     ▲                                                   |
                     |                                                   |
                     |                                                   |
 _________       ____|_____                                          ____▼____
|         |◀----|  Action  |                                        |         |
| Web API |     | Creators |                                        |  Store  |
|_________|----▶|__________|                                        |_________|
                     ▲                                                   |
                     |                                                   |
                 ____|________           ____________                ____▼____
                |   User       |         |   React   |              | Change  |
                | interactions |◀--------|   Views   |◀-------------| events  |
                |______________|         |___________|              |_________|
*/

图片来源:[redux-tutorial](https://github.com/happypoulp/redux-tutorial/blob/master/00_introduction.js)

上图是大家再熟悉不过的redux数据流,从这个图中我们可以按照下面这个流程来敲代码:

component(渲染UI) -> action(定义用户操作动作) -> reducer(处理action动作) -> store(处理reducer绑定state和dispatch) -> component(用connect绑定component、用Provider重新渲染UI) -> ...

这里使用了create-react-app安装并start后把一些没用的文件清理掉,增加我们自己的文件

文件目录如下:

src
    component/
        Texture.js
    action/
        action.js
    reducer/
        reducer.js
    store/
        store.js
    App.js
    

好,目录文件大概就是这样子,正式开始敲代码


我的位置:component/Texture.js

首先从component开刀(View视图):

引入必要的依赖:

import React from 'react';

创建component(这里省去了propsTypes和defaultProps,仅仅为了方便展示):

const Texture = (props) => (
  <div>
    <h2>{props.str}</h2>
    <input onChange={props.onChange} placeholder={props.placeholder} />
  </div>
);

我的位置action/action.js

然后定义action,在这个例子中,我们只有一个动作,修改input值:onChange,在action中命名为onChangeAction,并传入一个参数e,返回包含type和value值的对象,最后暴露模块:

const onChangeAction = (e) => (
  {
    type: 'INPUTCHANGE',
    value: e.target.value
  }
);

export default onChangeAction;

我的位置reducer/reducer.js

定义完action之后,我们自然是想办法处理这个action,那么下一步就是创建reducer:

reducer接收两个参数,并返回新的state,第一个参数state要先设置初始值,否则返回undefined,第二个参数action,接收可能接收到的action参数。

state中设置我们在component中要用到并绑定在视图中显示的props值,就是此前定义的str和placeholder

在reducer内部,需要用到switch检测action的type并根据不同的type来处理相应的action

需要注意的是,我们必须要记得在default情况下返回state,否则若无匹配的action.type,state就会丢失。

const reducer = (state = { str: '✒️write something: ', placeholder: 'here?' }, action) => {
  switch (action.type) {
    case 'INPUTCHANGE':
      return {
        str: action.value
      };
    default:
      return state;
  }
};

export default reducer;

我的位置:store/store.js

我们知道reducer存在于store内,既然action和reducer都配置好了,接下来就轮到store了

引入redux中createStore模块和之前定义好的reducer,创建store:

import { createStore } from 'redux';
import reducer from '../reducer/reducer';
const store = createStore(reducer);

export default store;

我的位置:component/Texture.js

处理完成后我们再回到component中:

这么一来,我们只需要将store中的state和dispatch分别绑定在component中即可打通store中的state和component中的props的联系了,那么我们只需要react-redux提供的connect和Provider即可:

导入相关模块:

import { Provider, connect } from 'react-redux';
import store from '../store/store';
import onChangeAction from '../action/action';

创建mapStateToProps和mapDispatchToProps两个函数:

const mapStateToProps = (state) => {
  return ({
    str: state.str,
    placeholder: state.placeholder
  });
};
const mapDispatchToProps = (dispatch) => {
  return ({
    onChange: (e) => { return dispatch(onChangeAction(e)) }
  });
};

并将这俩货和store通过connect和Provider绑定到视图中:

const TextureConnect = connect(mapStateToProps, mapDispatchToProps)(Texture);
const TextureWrapper = () => (
  <Provider store={store}>
    <TextureConnect />
  </Provider>
);
export default TextureWrapper;

我的位置:App.js

最后,大功告成,在App.js中引入这个组件即可。

//requirement
import React from 'react';
import TextureWrapper from './component/Texture';

const App = () => (
  <TextureWrapper />
);

export default App;

另外,component/Texture.js中视图部分最好单独出来,放在新建一个文件夹view目录下,并被名为TextureContainer.js引用,把其他逻辑部分放后者。


JS菌
6.4k 声望2k 粉丝