react + redux开发

react本身是组件化的,它的初衷只是提供一个UI库,但是在ES6以及webpack的大环境下,react本身已经形成了一整套全新的技术栈:
react: 提供视图模块
react-router: 提供视图路由切换,配合后端路由,可以开发比较强势的单页应用。
redux: 提供程序的数据状态管理机制。本身与react并没有直接联系,但是配合react可以更好地发挥react的作用。
webpack: 对react的jsx语法以及es6语法进行编译、对程序进行打包等等。
如果用react + redux开发一个todo程序,实现的步骤和难度会比使用angular要麻烦得多。但是从中可以学习到一些新的思想。

redux

redux本身的学习,基本只要记住它的三个东西:actionreducerdispatch

action

action描述的是一个最基本的动作。它返回一个对象,这个对象的属性里至少包含一个type属性,用来描述动作的行为标识,另外的各种属性则可以作为这个动作所携带的数据变化。
比如:

    const addItem = (text) => {
          return {
              type: 'ADD_ITEM',
              text
          }  
    }

这个函数就是一个action函数,它的动作类型是ADD_ITEM,动作携带的数据是函数传递进来的参数text
注意: 这里的action是一个函数,这是因为redux的dispatch风格实际上是一种函数式编程风格。

reducer

reducer也是一个函数,它用来描述一个action动作,会给程序的state带来怎样的变化。这个函数通常用一些switch语句来描述不同的action所改变的不同state。
比如:

    const Todo = (state = [], action) => {
            switch (action.type): {
                case: 'ADD_ITEM':
                return [
                  ...state,
                  {action.text}
                ]
                break;
                default:
                return state;
                break;  
            }
    }

注意:
reducer中的state一般会给一个默认值,然后就是一个原则:永远不要修改state本身的任何值。所以在上面的ADD_ITEM中,采用了ES6的数组继承的写法[...state, v]。如果state的表现形式是一个对象,那么就应该采用Object.assign的写法。
如果有多个reducer函数,则可以通过combineReducers函数将这一堆reducer给组合起来。

    const App = combineReducers({Todo})

dispatch

dispatch相当于事件触发,上面的reducers使用combineReducers组合完毕后,就可以使用redux的store了。

      let store = createStore(App);
      let unsubscribe = store.subscribe(() => {console.log(store.getState())});
      store.dispatch(addItem('hello redux'));
      unsubscribe();

使用createStore创建了程序的状态树,通过storesubscribe方法实现了sub/pub模式,并返回一个取消订阅的函数,这里用unsbuscribe变量接收。使用dispatch函数来触发action,改变state的当前状态。调用store.getState来获取程序的当前状态。直接调用unsubscribe()来取消订阅。
注意:唯一能够改变state状态的方法,就是触发action。这样的设计保证了程序状态的可控性和可预测性。

react-redux

react-redux是一个配合react使用的redux npm模块。在redux本身的基础上,提供了一个connect中间件,把react的UI与redux的数据结合了起来。
也就是说,react将更加专注地做自己的UI组件部分,redux则专注自己的数据部分,然后在传统的react component组件之外,新增了一个container组件。
react component只做自己的UI展示与逻辑,并不关心内部的props如何变化,也不知道传入自己的值是什么(但是可以通过PropTypes来规范传入值的数据类型)。
containers 组件则是先创建两个函数,一个是mapStateToProps,另一个是mapDispatchToProps,这两个方法会把reduxstatedispatch函数转化成reactprops,并且一切的数据操作都会由redux内部去管理和实现,然后通过react-reduxconnect方法,把redux的数据与react的组件结合起来。

    connect(mapStateToProps, mapDispatchToProps)(App);

上述的各种操作都是以函数为单位的,最为典型的就是connect函数,它接收两个函数作为参数,并且返回一个函数,这个返回的函数又是以函数作为参数的。所以这种函数编程的写法需要理解和习惯。毕竟JavaScript天生就是适合函数式编程的。

推荐阅读更多精彩内容