我在理解这个流程图的时候,采用的是一种容易记住的办法,而且贴切实际工做职责。
咱们能够把整个Redux工做流程理解成一个图书馆中借书操做。css
所以当咱们理解了每一个部位的身份后,咱们就按照着上面工做流程图一块儿来屡一下整个过程。首先借书的人(React Component)发起一个借书的实际操做(Action Creators)传达(dispatch)一个(action)给图书馆管理员(Store),图书馆管理员须要查阅借书小本本(Reducer),查阅完之后图书馆就能从借书小本本中获取到返回(return)的信息,再告诉借书的人“OK,我在借书小本本我登记好了,书你能够拿走了”,这样借书的人(React Component)就拿走书了。react
是否是如今有点印象对于整个工做流程?chrome
(说了这么多,不练下怎么知道爽不爽呢?)
npm
咱们要实现的功能很简单,就是经过redux去管理数据,数据[1, 2, 3]这时候都是从reducer中取出来的。
redux
主要展现两个分别为index.js和todoList.js数组
import React from 'react'; import ReactDOM from 'react-dom'; import TodoList from './TodoList'; ReactDOM.render(<TodoList />, document.getElementById('root'));
话很少说!浏览器
import React, { Component } from 'react'; import 'antd/dist/antd.css'; import { Input, Button, List } from 'antd'; import store from './store'; // 等价于 import store from './store/index.js' import { getInputChangeAction, getAddItemAction, getDeleteitemAction } from './store/actionCreator'; class TodoList extends Component { constructor(props) { super(props); this.state = store.getState(); this.handleInputChange = this.handleInputChange.bind(this); this.handleStoreChange = this.handleStoreChange.bind(this); this.handleBtnClick = this.handleBtnClick.bind(this); store.subscribe(this.handleStoreChange); //store中的数据只要被改变,就会自动触发里面的动做 } render() { return ( <div style={{marginTop: '10px', marginleft: '10px'}}> <div> <Input value={this.state.inputValue} placeholder='todo info' style={{width: '500px', marginRight: "10px"} } onChange={this.handleInputChange} > </Input> <Button type="primary" onClick={this.handleBtnClick}>提交</Button> </div> <List style={{marginTop: '10px', width: '500px'}} bordered dataSource={ this.state.list } renderItem={ (item, index) => (<List.Item onClick={this.handleItemDelete.bind(this, index)}> {item} </List.Item>) } > </List> </div> ) } handleInputChange(e) { /* 原代码,现将action封装到一个独立的actionCreator.js中 便于维护 const action = { type: CHANGE_INPUT_VALUE, value: e.target.value } */ const action = getInputChangeAction(e.target.value); store.dispatch(action) } handleStoreChange() { this.setState(store.getState()); } handleBtnClick() { const action = getAddItemAction(); store.dispatch(action); } handleItemDelete(index) { const action = getDeleteitemAction(index); store.dispatch(action); } } export default TodoList;
简单说两句上述代码。
1).渲染一个输入框一个按钮,点击按钮,将输入框中的数据发送store中并更改list的值,而后组件会接收到store数据变动将新数据渲染。
2).点击列表中的每一项会删除该项。其实就是组件发送一个action给store,告诉它,删掉我点的!
antd
npm install redux --save--dev
store文件总共有四个文件分别以下
dom
// index.js import { createStore } from 'redux'; import reducer from './reducer'; const store = createStore( reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() ); export default store;
简单解释两句以上代码,从redux中引入一个createStore方法,经过这个方法传入咱们的小本本reducer,建立一个store。那么问题来了,第二个参数这么一长条是啥玩意?莫慌兄dei~咱们为了更好的管理数据经过使用redux去管理,那么chrome有一个Redux Devtools插件能够可视化redux数据。而这一长条就是为了告诉浏览器,据说你有redux可视化数据的插件?还不快给老子显示一下redux数据!
异步
import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes'; export const getInputChangeAction = (value) => ({ type: CHANGE_INPUT_VALUE, value }); export const getAddItemAction = () => ({ type: ADD_TODO_ITEM }); export const getDeleteitemAction = (index) => ({ type: DELETE_TODO_ITEM, index });
1).简单说两句上面的代码,就是导出了三个得到action的方法,由于咱们用redux去管理数据的一个目的就是,咱们不在把业务逻辑放在React Component中,而是全封装在一个actionCreator中。而后咱们就能够在React Componet中直接引入actionCreator,而后吊用其中暴露的接口便可得到一个action,而后再把这个action派发给reducer。
2).那么再说两句action,在redux中action是一个对象,这个对象中有一个参数是type,记录的就是一个咱们须要怎样的操做(换句话说就是这是一个怎样的action),当咱们记录了这个type的时候,咱们就能够在reducer小本本中根据咱们所须要的type从而如何去改变store中的数据;其action这个对象中别的参数能够是咱们作这个操做时须要的别的value。
// actionTypes.js export const CHANGE_INPUT_VALUE = 'change_input_value'; export const ADD_TODO_ITEM = 'add_todo_item'; export const DELETE_TODO_ITEM = 'delete_todo_item';
简单说两句上述代码,这个文件实际上是对action中的type进行封装成一个常量。这样作的目的是:若是是一个普通字符串,当咱们在一个项目中屡次拼写的时候极可能会一个字符没拼对而出bug,而这个bug咱们还有可能花一天的时间去找,最后你可能会
有童鞋可能会说,我都复制还不行吗!行!累不累?可是,既然要用redux去管理数据,咱们就一劳永逸吧!
  //reducer.js import { CHANGE_INPUT_VALUE, ADD_TODO_ITEM, DELETE_TODO_ITEM } from './actionTypes'; const defaultState = { inputValue: '123', list: [1, 2, 3] }; export default (state = defaultState, action) => { // 更改input輸入框的值 if (action.type === CHANGE_INPUT_VALUE) { const newState = JSON.parse(JSON.stringify(state)); //深拷貝 newState.inputValue = action.value; return newState; } // 将input提交的值插入到数组list中 if (action.type === ADD_TODO_ITEM) { const newState = JSON.parse(JSON.stringify(state)); newState.list.push(newState.inputValue); newState.inputValue = ''; console.log(newState); return newState; } //刪除item if (action.type === DELETE_TODO_ITEM) { const newState = JSON.parse(JSON.stringify(state)); newState.list.splice(action.index, 1); return newState; } return state; }
老规矩,讲代码!
1.一般咱们定义仓库的一个默认值defaultState。
2.咱们导出一个方法。这个方法作的事情就是先记录不一样的action.type执行不一样的操做,返回给store对应操做后的数据。
总结:
当React Component须要执行一个操做时,就会调用actionCreator暴露的接口得到一个action,而后将这个action去dispatch给store,store拿到这样一个action就会去查小本本,而后根据小本本预先设定好的操做执行并返回对应的结果给store,而后store中的数据就会改变。咱们一般在React Component的constructor初始化时,执行store.subscribe(this.handleStoreChange)。表示的是,当store数据变化时,就会触发里面的操做拿到最新的数据。
后续会继续更新
1.redux-thunk,这个插件使得action除了对象外还能够是一个函数,这样咱们能够将一个异步请求,从react组件中封装到store中的actionCreator进行管理。
2.redux-immutable ,这个插件使得store中的数据成为一个immutable不可变对象
3.react-redux,链接父子组件的store,使得父组件中引入了store后,如何在子组件中链接并使用这个store
----------------做者的话:若是你看到了这里,那说明你真的是一个棒棒哒,第一次发博,码文码字还不是特别专业,不过会慢慢进步的,若有不对的地方,还请你们指点一下!--------------