单向数据流

单向数据流只关注于在store中维护的唯一的state,消除了不必要的多种states带来的复杂度.
这个store应该具有能被我们订阅(subscribe)store中变化的能力,实现如下:

  1. var Store = {
  2. _handlers: [],
  3. _flag: '',
  4. onChange: function (handler) {
  5. this._handlers.push(handler);
  6. },
  7. set: function (value) {
  8. this._flag = value;
  9. this._handlers.forEach(handler => handler())
  10. },
  11. get: function () {
  12. return this._flag;
  13. }
  14. };

然后我们会在我们的App组件上加上订阅我们的store的钩子, 当每次store发生改变的时候, 我们的组件就会被重新的渲染.

  1. class App extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. Store.onChange(this.forceUpdate.bind(this));
  5. }
  6. render() {
  7. return (
  8. <div>
  9. <Switcher
  10. value={ Store.get() }
  11. onChange={ Store.set.bind(Store) }/>
  12. </div>
  13. );
  14. }
  15. }

请注意我们使用了forceUpdate这个函数,但是事实上我们并不推荐使用这个函数.

一般情况下我们会使用高阶组件去帮我们处理重新渲染的事情,我们在这里使用forceUpdate函数只是想尽可能的保持我们这个例子简单.

因为我们使用了store, Swticher这个组件就变得超级简单了. 我们不需要再在Switcher组件内部再去维护一份State了:

  1. class Switcher extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this._onButtonClick = e => {
  5. this.props.onChange(!this.props.value);
  6. }
  7. }
  8. render() {
  9. return (
  10. <button onClick={ this._onButtonClick }>
  11. { this.props.value ? 'lights on' : 'lights off' }
  12. </button>
  13. );
  14. }
  15. }

使用单向数据流的好处是我们的组件在这种情况下变得非常声明式, 成为了所谓的纯UI组件, 只是我们Store里面数据的表达.
React在诞生之初就是为了解决视图层(View层)的问题, 其核心思想也是从视图出发去解决问题. 我们用声明式的方式去构建我们的应用, 让我们的组件变得尽可能的木偶化,只关心我们的数据,将我们的复杂的数据逻辑交由我们的store去处理. 这也是我们去构建React应用的时候的一种比较好的思路.

参考资料: