首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 Redux 实现时间旅行-3

使用 Redux 实现时间旅行-3

状态控件在本系列的  中,我讨论了控件组件,它(像 Redux        应用程序中的许多组件一样)被拆分为一个容器组件和一个包含的无状态组件。容器组件将主题和显示模式映射到无状态组件。此外,该无状态组件(如清单 5 所示)包含          HistoryContainer 组件,所有时间旅行操作都在该组件中发生。
清单 5. 控件无状态组件          (components/controls.js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import React from 'react';
import DisplayModeContainer from '../containers/displayMode';
import TopicSelectorContainer from '../containers/topicSelector';
import HistoryContainer from '../containers/history';

const Controls = ({
  topic,
  displayMode
}) => {
  const styles = {
    controls: {
      padding: '15px',
      marginBottom: '25px'
    }
  };

  return(
    <div style={styles.controls}>
      <TopicSelectorContainer topic={topic} />
      <DisplayModeContainer displayMode={displayMode} />
      <HistoryContainer />
    </div>
  );
}

Controls.propTypes = {
  displayMode: React.PropTypes.string.isRequired,
  topic: React.PropTypes.string.isRequired,
};

export default Controls;




历史容器和无状态组件HistoryContainer 组件如清单 6 所示。
清单 6. 历史容器          (containers/history.js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { connect } from 'react-redux';
import { undo, redo, gotoState } from '../actions';
import { History } from '../components/history';
import stateHistory from '../statehistory';

const mapStateToProps = state => {
  return {
    past: stateHistory.past,
    present: stateHistory.present,
    future: stateHistory.future
  }
}

const mapDispatchToProps = dispatch => {
return {
   undo: () => {
     dispatch(undo());
   },

   redo: () => {
     dispatch(redo());
   },

  gotoState: stateIndex => {
     dispatch(gotoState(stateIndex));
   }
}
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(History);




历史容器将 past、present 和 future 作为属性映射到它包含的          History 组件。它还将 3 个函数(undo()、redo() 和          gotoState())作为属性映射到 History 组件。
请注意,将历史容器映射到其无状态组件的函数都会分派 Redux 操作。实现时间旅行涉及到更改状态,清单 6 中的函数通过分派 Redux        操作来实现此目的。操作是由操作创建器创建的,如清单 7 所示。
清单 7. 历史操作创建器          (actions.js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...

export const redo = () => {
  return {
    type: 'REDO'

  }
}

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

export const gotoState = stateIndex => {
  return {
    type: 'GOTO',
    stateIndex
  }
}




与操作创建器中的常见情况一样,清单 7 中的操作创建器很简单 — 它们仅返回操作对象。只有 gotoState        操作提供了状态更改类型以外的信息。该信息是历史对象所维护的状态数组的索引。
清单 8 显示了 history 无状态组件。
清单 8. history          无状态组件        (components/history.js)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import React from 'react';

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

    link: { textDecoration: 'none' },
    input: { cursor: 'pointer' }
  }

  const RightArrow = () => {
    return(
      <a href='#' style={styles.link}
                  onClick={() => redo()}> →
      </a>
    );
  }

  const LeftArrow = () => {
    return(
      <a href='#' style={styles.link}
                  onClick={() => undo()}> ←
      </a>
    );
  }

  const maxRange = () => {
    return (past   ? past.length   : 0) +
           (present? 1 : 0)             +
           (future ? future.length : 0) - 1;
  }

  return(
    <span style={styles.container}>
      History

      <input type='range'
             style={styles.input}
             min={0}
             max={maxRange()}
             value={past ? past.length : 0}
             onChange={event => gotoState(event.target.value)}/>

      { (past   && past.length   > 0) ? <LeftArrow />  : null }
      { (future && future.length > 0) ? <RightArrow /> : null }
    </span>
  )
}

History.propTypes = {
  past: React.PropTypes.array.isRequired,
  present: React.PropTypes.object.isRequired,
  future: React.PropTypes.array.isRequired,

  undo: React.PropTypes.func.isRequired,
  redo: React.PropTypes.func.isRequired,
  gotoState: React.PropTypes.func.isRequired,
};




history 无状态组件显示历史滑块和箭头。当用户单击某个箭头时,此组件调用它以属性形式从包含它的容器组件收到的相应          undo() 或 redo() 函数。
当用户操作滑块时,历史无状态组件会调用 gotoState() 函数,该函数也是它以属性形式从包含它的容器中收到的。
目前为止,为了实现历史和撤销/重做功能,我实现了一个跟踪过去、现在和未来的状态历史对象。我介绍了 React 组件的实现,这些组件包含操作当前状态的控件和显示该状态的 HTML        元素。
这里保留了一个关键功能:处理  中定义的 undo、redo 和          goto 操作。接下来,我将介绍如何执行这些操作。
返回列表