Redux分析

1、前言

redux是什么?

Flux演变而来,做为状态容器,提供可预测的状态管理。html

为何要用redux?

  • 复杂应用中没法获取操做记录,而状态的改变每每意味着对应视图的变化,这一过程是不可控的。前端

    提供一种机制,统一对状态的查询、改变、应用进行管理,同时对每一次的状态变动可进行回溯追踪vue

  • 多个组件件间可能存在数据的共享以及通讯。react

    这里能够简单将其理解为充当了eventBus的角色。git

  • 视图的改变以及数据的获取等操做杂糅在一块儿,不利于维护github

    具体操做 -> 状态变动 -> 触发视图更新,这一单向数据流的控制,不只使得对状态变化的过程变得可控,同时解耦了数据M和视图V。见下图,针对相同的action,其数据流转以及state管理是独立于前端模板的,所以能够实现跨框架的复用。 数据和视图的解耦web

redux适用全部项目?

  • 需不须要使用redux,仍是要结合项目实际以及业务需求,它只是web架构的一种解决方案。好比彻底没有仅仅由于第二种组件通讯而使用,目前的主流框架如vue有vuex、依赖注入等实现。
  • react使用flux,主要是由于react只提供了组件化UI,视图模板渲染的一种解决方案,并无提供诸如双向绑定之类的对数据流的管理。

2、Redux概述

Redux主要有以下几个概念:vuex

  • action:通常写法:<type:操做意图(通常定义为字符串常量), payload:{text:"要改变的新数据"}>,是store数据的惟一来源。redux

  • store:Redux应用只有一个单一的store。当须要拆分数据处理逻辑时,你应该使用 reducer 组合而不是建立多个store。(经常使用方法:dispatchgetStatesubscribe等)缓存

  • state:数据对象,由store对象管理,经过getStore()只读

    改变的惟一途径:由store的dispatch方法对action进行分发,reducer进行处理 范式化。

  • reducer:对action作出相应响应,返回新生成的state(这也是保证可回溯的缘由)。 新生成state有以下几种方式:

    • Object.assign({}, oldState, newState)
    • {...oldSate, 新值}
    • Immutable
  • 中间件

    这里强调下Redux的中间件使用,在每次action触发时,都会先经过层层中间件再真正执行。这个过程赋予了咱们诸如日志记录等能力。洋葱圈模型,和KOA的中间件原理相似。

运做原理图以下: 运做流程图

3、Redux分析

如下是仿Redux写的demo,实现了Redux的基本能力,缓存了操做记录,进一步扩展能够实现诸如回退等功能。

如下列出了几个核心函数:

  • store

    /**
    * store提供的方法:
     *  1. getState:获取当前state
    *  2. dispatch:触发行为
    *  3. subscribe:订阅事件
     */
     function createStore(reducers, initState) {
        //historyState可用做时光机
        let state = initState, historyState = [{action:'init', state: initState}], listeners = [];
    
        let getState = () => state;
    
        let subscribe = (event) => {
           listeners.push(event);
            /**
             * 注册事件的同时,获取事件句柄
             * let fnHandle = fnsubscribe(fn)
             * 删除对应注册事件
             * fnHandle();
            *  */
            return () => {
                listeners = listeners.filter(eventItem => eventItem != event);
            }
        }
    
     let dispatch = (action) => {
        //reducer根据action对state作改变,返回全新的state
         state = reducers(state, action);
         historyState.push({action, state})
         //state改变的状况下,触发事件
         listeners.forEach(listener => listener());
      }
     return {
          dispatch,
          getState,
           subscribe,
           getHistoryState: () => historyState
       }
    }
    复制代码
  • 绑定中间件applyMiddleware

    //将中间件绑定到
    let applyMiddleware = middlewares => (createStore) => (...args) => {
      let store = createStore(...args);
       let dispatch = store.dispatch;
      let params = {
          dispatch,
          getState: store.getState
      };
       middlewares = middlewares.map(mw => mw(params));
      //组合中间件,加强dispatch
      //装饰者模式 & 洋葱圈,compose对中间件的组合
       dispatch = compose(middlewares)(dispatch);
      //返回加强后的dispatch
       return Object.assign(store, {dispatch});
    }
    复制代码
  • 使用

    • reducers
      /**
       * 对action作处理,返回全新的state
       */
      function reducers(state, action){
          switch(action){
              case 'add':
                  return state += 1;
              case 'minus':
                  return state -=1;
              default:
                  return 0;
          }
      }
      复制代码
    • middleware
      /**
      * 中间件(注意中间件的约定格式)
       */
      function middleware1({dispatch, getState}) {
         return function(next) {
             return function(action) {
                 console.log(`【日志】当前state值:${getState()},执行${action}`);
                next(action);
                console.log(`【日志】操做完成后,state值:${getState()}`);
           }
        }
      }
      function middleware2({dispatch, getState}) {
         return function(next) {
             return function(action) {
                 console.log(`>>>>>>>>>>>>>>>>>>`);
                  next(action);
               console.log(`<<<<<<<<<<<<<<<<<<`);
            }
       }
      }
      复制代码
    • 初始化store
      /**
       * 对外暴露:
       *  1. createStore: 产生store
       *  2. applyMiddleware:中间件处理
       */
      let initState = 1;
      let store = applyMiddleware([middleware2, middleware1])(createStore)(reducers, initState);
      
      复制代码

4、展现

demo展现效果以下:

这里只是简单说明redux的能力,具体功能可自行扩展。

完整代码见:github.com/269117220/w…

参考文献

相关文章
相关标签/搜索