React:如何在挂载后读取DOM?

时间:2015-11-23 05:05:32

标签: javascript dom reactjs flux

在我的React组件中,当需要为我的应用程序的后续部分工作时,我需要从DOM中读取数据。我需要将数据保持在状态,并通过调度动作通过Flux发送。这样做有最好的做法吗?

更具体地说,我至少在两种情况下需要来自DOM的数据:

  • 视觉上立即,就像用户看到的第一件事应该是“正确的”,这涉及基于从DOM读取的数据的计算。
  • 稍后使用的数据(例如用户移动鼠标),但基于初始DOM状态。

请考虑以下事项:

  • 我需要从DOM读取并保存数据。这个DOM在componentDidMount中可用,但是我无法在componentDidMount 中发送操作,因为这会在调度错误期间发生调度。因此,在component*mount中调度是React中的反模式。
  • 上述常用的解决方法(hack)是将componentDidMount内的调度放入setTimeout( ..., 0 )调用中。 我想避免这种,因为它似乎纯粹是一种绕过Flux错误的黑客攻击。如果真的没有更好的答案,我会接受它,但不情愿。
  • 不要用不读取DOM来回答这个问题。这与我的要求无关。我知道这会将我的应用程序与DOM结合,我知道这不是所希望的。同样,我问的问题与我是否应该使用这种方法无关。

1 个答案:

答案 0 :(得分:0)

这是我在回流中使用的模式。



export default class AppCtrl extends AppCtrlRender {
  constructor() {
    super();
    this.state = getAllState();
  }

  componentDidMount = () => {
    // console.log('AppCtrl componentDidMount');
    this.unsubscribeApp = AppStore.listen(this.appStoreDidChange);
    this.unsubscribeGS = GenusSpeciesStore.listen(this.gsStoreDidChange);
    Actions.setWindowDefaults(window);
  }
  componentWillUnmount = () => { this.unsubscribeApp(); this.unsubscribeGS(); }
  appStoreDidChange = () => { this.setState(getAppState()); }
  gsStoreDidChange = () => { this.setState(getGsState()); }
  shouldComponentUpdate = (nextProps, nextState) => {
    return nextState.appStoreChanged && nextState.gsStoreChanged;
  }
}




在app.store.js中



function _windowDefaults(window) {
  setHoverValues();
  let deviceTyped = 'mobile';
  let navPlatform = window.navigator.platform;
  switch (navPlatform) {
    case 'MacIntel':
    case 'Linux x86_64':
    case 'Win32': deviceTyped = 'desktop'; break;
  }
  //deviceTyped = 'mobile';
  _appState.deviceType = deviceTyped;
  _appState.smallMobile = (deviceTyped == 'mobile' && window.screen.width < 541);
  //_appState.smallMobile = (deviceTyped == 'mobile');
  if (deviceTyped == 'desktop') {
    let theHeight = Math.floor(((window.innerHeight - 95) * .67));
    // console.log('_windowDefaults theHeight: ', theHeight);
    _appState.commentMaxWidth = theHeight;
    _appState.is4k = (window.screen.width > 2560);
    Actions.apiGetPicList();
  } else {
    React.initializeTouchEvents(true);
    _bodyStyle = {
      color: "white",
      height: '100%',
      margin: '0',
      overflow: 'hidden'
    };
    AppStore.trigger();
  }
}
&#13;
&#13;
&#13;