反应:渲染后无法获得正确的元素宽度

Gil*_*ler 2 javascript iframe width reactjs

如果一段文本大于它的容器,我试图在React中设置一个选取框,但即使组件已渲染,我也无法获得正确的容器宽度。

我读了另一个答案React“渲染后”代码?您必须使用我正在尝试的requestAnimationFrame,但仍无法正常工作。

如果我记录容器的宽度,它会显示147px的宽度,该宽度是在样式表中使用min-width设置的,但是正确的宽度应该是320px,当屏幕的min-width是600px时,使用媒体查询可以设置该宽度。

这是一个子组件,如果有任何区别,并且iFrame的宽度超过600像素,则父组件将呈现在iFrame中。

JS:

module.exports = React.createClass({

  componentDidUpdate: function () {
    // Setup marquee
    this.initMarquee();
  },

  render: function () {
    // Setup marquee
    this.initMarquee();

    var artistName = this.props.artist.artistName;
    var trackName  = this.props.track.trackName;

    return (
      <div className="MV-player-trackData no-select" ref="mvpTrackData">
        <div className="MV-player-trackData-marquee-wrap" ref="mvpMarqueeWrap">
          <div className="MV-player-trackData-marquee" ref="mvpMarquee">
            <a className="MV-player-trackData-link no-select" href={this.props.storeUrl} target="_blank">
              <span id="mvArtistName">{artistName}</span> &ndash; <span id="mvTrackName">{trackName}</span>
            </a>
          </div>
        </div>
      </div>
    )
  },

  initMarquee: function () {
    if ( typeof requestAnimationFrame !== 'undefined' ) {
      //store a this ref, and
      var self = this;
      //wait for a paint to setup marquee
      window.requestAnimationFrame(function() {
        self.marquee();
      });
    }
    else {
      // Suport older browsers
      window.setTimeout(this.marquee, 2000);
    }
  },

  marquee: function () {
    var marquee     = React.findDOMNode(this.refs.mvpMarquee);
    var marqueeWrap = React.findDOMNode(this.refs.mvpMarqueeWrap);

    // If the marquee is greater than its container then animate it
    if ( marquee.clientWidth > marqueeWrap.clientWidth ) {
      marquee.className += ' is-animated';
    }
    else {
      marquee.className = marquee.className.replace('is-animated', '');
    }
  }

});
Run Code Online (Sandbox Code Playgroud)

CSS:

.MV-player-trackData-marquee-wrap {
  height: 20px;
  line-height: 20px;
  min-width: 147px;
  overflow: hidden;
  position: relative;
  width: 100%;

  @media only screen and (min-width : 600px) {
    min-width: 320px;
  }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了许多不同的解决方案,包括布局react-component-width-mixin,但是它们都不起作用。我尝试对组件宽度mixin做出反应,因为在我的应用程序的另一部分中,我尝试获取的值,window.innerWidth但在渲染后也返回0,除非我将超时设置为大约2秒,但是不幸的是,有时2秒的时间不够长由于数据加载和其他回调,因此可以轻松刹车。

任何帮助都非常感谢。谢谢。

更新: 正确的答案之一是指出我应该在this.initMarquee();内部进行调用componentDidMount,但是不幸的是,我在测试时粘贴了错误的代码,以查看在内部进行调用是否有所不同render。正确的代码如下所示:

componentDidMount: function () {
  // Setup marquee
  this.initMarquee();
},
Run Code Online (Sandbox Code Playgroud)

不幸的是,这也不起作用,我仍然收到不正确的marqueeWrap宽度。

更新:2015年6月24日 为了澄清,这是我要实现的字幕效果,仅当文本大于其容器时才显示,因为当文本不大于其容器时毫无意义地滚动它。

另外,这里还有一个来自React团队的Github Issue的链接,其中谈到了React为什么在浏览器绘制之前进行渲染。-既然如此,我想知道如何可靠地获取所讨论元素的宽度。

Zap*_*ree 5

可能发生的一个问题是,在componentDidMount触发时,您的CSS尚未加载。使用webpack可能会发生这种情况,并且即使您的项目中的组件之前已包含css,也将css包含在还包含js的包中。