热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

redux时间旅行,你值得拥有!

顾名思义,就是可以随时穿越到以前和未来,让应用程序切换到任意时间的状态。我们都知道,一般应用状态都很

顾名思义,就是可以随时穿越到以前和未来,让应用程序切换到任意时间的状态。我们都知道,一般应用状态都很复杂,创建、维护、修改和弄明白有哪些行为会影响状态都不是一件容易的事儿。

redux 的解决方案

整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。并使用纯函数计算下一个应用程序状态(不允许其他途径对 state 进行修改)。这些特征使 Redux 成为了一个可预测 的状态容器,这意味着如果给定一个特定应用程序状态和一个特定操作,那么应用程序的下一个状态将始终完全相同。这种可预测性使得实现时间旅行变得很容易。redux 也相应的开发了一个带时间旅行的开发者工具 redux-devtools

redux 时间旅行,你值得拥有!

就是上面这个东西。下面就让我们跟随例子一起来了解下 redux 时间旅行的工作原理。

阅读要求

  • react 基础
  • redux 基础,明白 action,reducer,state 的关系。明白 combineReducer 的原理。

开始

项目地址:(github)[ github.com/wuyafeiJS/r… ]

预览:

redux 时间旅行,你值得拥有!
既然我们要实现时间旅行,那么第一步我们需要一个对象来记录每一次状态: stateHistory.js
export default {
  past: [],
  futrue: [],
  present: undefined,
  gotoState(i) {
    const index = i * 1;
    const allState = [...this.past, this.present, ...this.futrue];
    this.present = allState[index];
    this.past = allState.slice(0, index);
    this.futrue = allState.slice(index + 1, allState.length);
  }
};

我们把状态分为三个时间段:过去,现在(只有一个状态),将来。gotoState 函数则是用来做时间旅行的,他的实现方式就是整合所有状态 allState,重新分配,present 前面是 past,后面是 future。

那么我们如何去存放每一次变更的状态呢?我们需要找到一个入口,这个入口必须是每次触发状态变更都会经过的地方。而触发状态变更唯一的方式就是 dispatch(action) ,想想,这样的地方好像只有一个地方,看过 redux 源码的同学肯定就是不陌生,那就是 combineReducer 生成的 reducers 纯函数。 combineReducer 负责整合多个 reducer,最终返回一个能够处理所有 action 的 reducers。让我们大致简单实现一下:

const combineReducer = obj => (state, action) => {
  const finalState = {};
  for (key in obj) {
    finanlState[key] = obj[key](state[key], action);
  }
  return finalState; // 全局state
};

接下来,让我们利用函数式编程的思想加强下 reducers 的功能,让它能记录 state: reducers.js

import stateHistory from './stateHistory';// 引入我们之前声明的history对象

// 原本我们是这样返回reducers的
export default combineReducers({
    books: fetchReducer,
    displayMode: bookDisplayReducer,
    currentStatus: statusReducer,
    topic: topicReducer
})
// 改造后如下:
export default history(
  combineReducers({
    books: fetchReducer,
    displayMode: bookDisplayReducer,
    currentStatus: statusReducer,
    topic: topicReducer
  })
);
// 我们用history包裹combineReducer,history实现如下
const history = reducers => (state, aciton) => {
  switch (action.type) {
    case 'UNDO': // 后退
      stateHistory.undo();
      break;
    case 'REDO': // 前进
      stateHistory.redo();
      break;
    case 'GOTO': // 定点指向
      stateHistory.gotoState(action.stateIndex);
      break;
    default:
      const newState = reducer(state, action);
      stateHistory.push(newState);// 每次dipatch(action)都会像将状态保存到stateHistory
  }
  return stateHistory.present; // 返回当前状态
}

完善下 stateHistory.js

export default {
  ...

  hasRecord(type) {// 查询是否有过去或者将来的状态
    return this[type].length > 0;
  },
  hasPresent() { // 查询是否有现在的状态
    return this.present !== undefined;
  },
  setPresent(state) {
    this.present = state;
  },
  movePresentToPast() {
    this.past.push(this.present);
  },
  push(currentState) { // 将状态都保存,并更新当前状态
    if (this.hasPresent()) {
      this.past.push(this.present);
    }
    this.setPresent(currentState);
  },
  getIndex() { // 获取当前状态index
    return this.past.length;
  },
  undo() { // 后退
    if (this.hasRecord('past')) {
      this.gotoState(this.getIndex() - 1);
    }
  },
  redo() { // 前进
    if (this.hasRecord('futrue')) {
      this.gotoState(this.getIndex() + 1);
    }
  },
  ...
};

配置 action: actions.js

...
export const redo = () => ({
  type: 'REDO'
});

export const undo = () => ({
  type: 'UNDO'
});

export const gotoState = stateIndex => ({
  type: 'GOTO',
  stateIndex
});

准备工作都已经做完,接下来咱们直接在 react 组件内加上触发代码即可 components/History.js

const History = ({ past, futrue, present, redo, undo, gotoState }) => {
  const styles = {
    container: {
      marginLeft: '20px',
      cursor: 'pointer'
    },

    link: { textDecoration: 'none' },
    input: { cursor: 'pointer' }
  };
  const RightArrow = () => (
    // 前进
     redo()}>
       
    
  );

  const LeftArrow = () => (
    // 后退
     undo()}>
       
    
  );
  const max = () =>
    (past ? past.length : 0) +
    (present ? 1 : 0) +
    (futrue ? futrue.length : 0) -
    1;
  const value = () => (past ? past.length : 0);
  return (
    
       {
          gotoState(e.target.value);
        }}
        style={styles.input}
      />
      {past && past.length > 0 ?  : null}
      {futrue && futrue.length > 0 ?  : null}
    
  );
};

以上!希望对大家理解 redux 有所帮助。


以上所述就是小编给大家介绍的《redux 时间旅行,你值得拥有!》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 我们 的支持!


推荐阅读
  • 本文探讨了异步编程的发展历程,从最初的AJAX异步回调到现代的Promise、Generator+Co以及Async/Await等技术。文章详细分析了Promise的工作原理及其源码实现,帮助开发者更好地理解和使用这一重要工具。 ... [详细]
  • 利用Node.js实现PSD文件的高效切图
    本文介绍了如何通过Node.js及其psd2json模块,快速实现PSD文件的自动化切图过程,以适应项目中频繁的界面更新需求。此方法不仅提高了工作效率,还简化了从设计稿到实际应用的转换流程。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 本文详细介绍了 `org.apache.tinkerpop.gremlin.structure.VertexProperty` 类中的 `key()` 方法,并提供了多个实际应用的代码示例。通过这些示例,读者可以更好地理解该方法在图数据库操作中的具体用途。 ... [详细]
  • 本文深入探讨了Go语言中的接口型函数,通过实例分析其灵活性和强大功能,帮助开发者更好地理解和运用这一特性。 ... [详细]
  • 入门指南:使用FastRPC技术连接Qualcomm Hexagon DSP
    本文旨在为初学者提供关于如何使用FastRPC技术连接Qualcomm Hexagon DSP的基础知识。FastRPC技术允许开发者在本地客户端实现远程调用,从而简化Hexagon DSP的开发和调试过程。 ... [详细]
  • Web动态服务器Python基本实现
    Web动态服务器Python基本实现 ... [详细]
  • 理解浏览器历史记录(2)hashchange、pushState
    阅读目录1.hashchange2.pushState本文也是一篇基础文章。继上文之后,本打算去研究pushState,偶然在一些信息中发现了锚点变 ... [详细]
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • 本文探讨了Python类型注解使用率低下的原因,主要归结于历史背景和投资回报率(ROI)的考量。文章不仅分析了类型注解的实际效用,还回顾了Python类型注解的发展历程。 ... [详细]
  • 本文将详细探讨 Python 编程语言中 sys.argv 的使用方法及其重要性。通过实际案例,我们将了解如何在命令行环境中传递参数给 Python 脚本,并分析这些参数是如何被处理和使用的。 ... [详细]
  • 本文探讨了如何通过优化 DOM 操作来提升 JavaScript 的性能,包括使用 `createElement` 函数、动画元素、理解重绘事件及处理鼠标滚动事件等关键主题。 ... [详细]
  • 如何将955万数据表的17秒SQL查询优化至300毫秒
    本文详细介绍了通过优化SQL查询策略,成功将一张包含955万条记录的财务流水表的查询时间从17秒缩短至300毫秒的方法。文章不仅提供了具体的SQL优化技巧,还深入探讨了背后的数据库原理。 ... [详细]
  • 深入探讨前端代码优化策略
    本文深入讨论了前端开发中代码优化的关键技术,包括JavaScript、HTML和CSS的优化方法,旨在提升网页加载速度和用户体验。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
author-avatar
Irises---_372
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有