我本身的理解redux就跟vue中的vuex差很少,都是数据管理器,话很少说,咱们从经典的计数器案例开始讲解vue
使用redux实现计数器react
建立以下的react项目,我习惯把每个模块分块,才有这么多文件,固然你也能够写在一个js文件中,这不是重点vuex
首先咱们看一下项目的入口文件index.js编程
import 'core-js/fn/object/assign'; import React from 'react'; import ReactDOM from 'react-dom'; import Counter from './components/Counter'; //引入计数器件 import {createStore} from 'redux'; //经过解构赋值获得createStore,为store的建立作准备 import reducer from './reducers/index' //引入reducer纯函数 该函数,根据action的type不一样结合旧的state返回新的state let store = createStore(reducer); //建立redux的核心 store store我会在后面进行详细的解答 import {numAdd,numDel} from './actions/index'; //引入action函数,触发什么操做,就根据操做怎样改变值 // Render the main component into the dom //这里使用Redducer变量来定义ReactDOM中的render函数,是方便store中state更新以后,页面的渲染 const Redducer = () =>{ ReactDOM.render( <Counter value={store.getState()} add ={()=>store.dispatch(numAdd())} del ={()=>store.dispatch(numDel())} ></Counter>, document.getElementById('app') ); }; // value={store.getState()} 给展现组件Counter传递数据 这里的store.getState()获得的值,就是store建立过程当中reducer纯函数里面的初始state值 // ()=>store.dispatch(numAdd())和()=>store.dispatch(numDel()) 定义函数传递给展现组件Counter //store.dispatch(参数)会传递一个对象做为参数例如{type:"add"},调用reducer纯函数,实现store中的state的更新 Redducer();//该函数执行,就初始化了页面 store.subscribe(Redducer); //store.subscribe()用来监听store中大的state是否发生改变,若是发生改变,就从新渲染页面,因此才跟Redducer()进行绑定
在看纯函数reducer,至于为何redux负责state编辑的函数统称reducer,我本身的猜想是根据es5中的reduce方法有关(纯属瞎猜想,切勿当真)redux
const reducer = (state=0,action)=>{ switch (action.type){ case 'add': return state+1; case 'del': return state-1; default: return state } }; //定义store的state = 0,action接受的值就是store.dispatch(numAdd())中经过numAdd()函数的到的一个对象 //因为前面在获得store的时候 该函数跟redux中的createStore进行了绑定 也就是这一句代码 let store = createStore(reducer) //因此经过这里就能够改变store的state值,因此说如今能够的理解reducer为何是一个纯函数了吧 export default reducer;
在看actions中的导出函数app
export const numAdd = ()=>{ return{ type:"add" } }; export const numDel = ()=>{ return{ type:"del" } } //导出两个函数,每个函数返回一个包含type属性的对象(注意ation中type是必须的,其余的属性能够自行添加),能够经过解构赋值获得每个 //的函数,就像入口文件index.js中的这一句代码 import {numAdd,numDel} from './actions/index';
最后看展现组件Counterdom
import React from 'react'; //函数返回组件的话,就是解构赋值获取数据 // const Counter = ({ value, add, del })=>{ // return( // <div> // <p style={{color:'red'}}> // 点击次数{value} // </p> // <button onClick={add}>加一</button> // <button onClick={del}>减一</button> // </div> // ) // }; //class返回组件的话,就是直接获取当前组件自身的属性,就能够获取到本身想要的数据 class Counter extends React.Component { render() { return ( <div> <p style={{color: 'red'}}> 点击次数{this.props.value} </p> <button onClick={this.props.add}>加一</button> <button onClick={this.props.del}>减一</button> </div> ) } } export default Counter;
在这里我使用了两种方式来建立组件,第一种经过函数的方式建立的组件,要获取在入口文件index.js中传过来的数据,只能经过形参解构赋值的到数据,第二种经过class建立的组件只能经过组件自身的属性,来获取数据,固然也能够经过解构赋值来获得本身想要的数据,代码以下异步
class Counter extends React.Component { render() { let {value,add,del} = this.props; return ( <div> <p style={{color: 'red'}}> 点击次数{value} </p> <button onClick={add}>加一</button> <button onClick={del}>减一</button> </div> ) }
综上全部的代码就能够实现了简单的计数器的功能,这就是redux最基本的使用方法,提示:redux和reat-redux须要本身安装,最好使用--save来安装ide
接下来就是使用redux和react-redux来实现计数器异步编程
且看代码
import React, { Component } from 'react' //引入react import PropTypes from 'prop-types' //引入限制UI组件(展现组件)属性限制 import ReactDOM from 'react-dom' //引入react-dom相关的对象 import { createStore } from 'redux' //引入redux import { Provider, connect } from 'react-redux'//引入react配套的redux // 建立react组件(或者是虚拟节点) class Counter extends Component { render() { const { value, onIncreaseClick } = this.props; //经过解构赋值获得相应的属性里面的值 //在这里Counter是UI组件(展现组件)其属性是其外面的容器组件中的state是经过react-redux中的connect操做以后传递过来的 return ( <div> <span>{value}</span> <button onClick={onIncreaseClick}>Increase</button> {/*经过点击事件触发绑定的属性,很明显,在这里onIncreaseClick是一个方法或者是一个对象的key值,其映射的value值是一个函数*/} </div> ) } } //对展现组件中属性各个值得类型进行限制 不合符规则会报错 Counter.propTypes = { value: PropTypes.number.isRequired, //属性对象中的value必须是number类型还有必须有值 onIncreaseClick: PropTypes.func.isRequired //属性对象中的onIncreaseClick必须是函数还有必须有值 }; // 这里定义的是一个action对象,个人理解就是跟vuex中actions的做用差很少,发送不一样的动做名称,经过配套其余函数的监听 //实现容器组件的状态(state)的改变,只不过vuex中的actions是发送动做名,redux是根据actions对象中的type的值不一样,进行不一样的操做 const increaseAction = { type: 'increase' }; // 定义reducer纯函数,reducer函数的做用就是,根据传过来的action和旧state的状态值 //而后根据action的type的值进行不一样的操做,进行新的state的返回,从而达到UI组件(展现组件)的从新渲染 function counter(state = { count: 0 }, action) { const count = state.count; switch (action.type) { case 'increase': return { count: count + 1 }; default: return state } } // 建立store对象,能够说store是redux的核心,由于根据redux的设计理念, //对state的操做都是根据store中的各类方法实现的,便于管理 //在这里规定使用redux中的createStore和reducer纯函数结合来获得咱们想要的store const store = createStore(counter); //mapStateToProps是connect的第一个参数 //根据名称咱们知道是把以前reducer纯函数中的state(状态)和展现组件的props(属性)进行映射 function mapStateToProps(state) { return { value: state.count } } // mapDispatchToProps是connect的第二个参数 //根据名称咱们能够知道是把reducer纯函数中以前store中的dispatch方法和展现组件的props(属性)进行映射 function mapDispatchToProps(dispatch) { return { onIncreaseClick: () => dispatch(increaseAction) } } // 这里定义App为react-redux设计理念中的容器组件 //经过connect中传递参数和展现组件Counter相结合得出相应的容器组件App //这里的容器组件App里面包含了展现组件Counter const App = connect( mapStateToProps, mapDispatchToProps )(Counter); //向目标元素渲染容器组件App //这里的组件Provider是一个react-redux中特殊的组件 //注意: 1. Provider中有且只有一个子组件(这里就是App容器组件,不必定是容器组件,根据本身的业务需求本身操做) // 2. 使用Provider组件的好处是,只须要给Provider组件设置属性,那么其子组件和其子组件中的子组件均可以直接使用其对应的属性 // 3. 避免了组件嵌套以后一个一个传递的复杂操做 ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('app') )
在这里就完成了redux和react-redux的结合使用,经过本身的学习,我发现了编程思想是多么的重要,我感叹于react-redux这种思想的深度,总体感受干净,使得展现组件和容组件既相互分离又有必定的结合,兼职就是藕断丝连,可是又不会违背组件分离的思想,简直就是强大
,好了基础的redux和react-redux的讲解就到此结束了,后面我还会写出redux异步编程的理解,毕竟如今的都是同步实现