簡體   English   中英

反應:渲染后無法獲得正確的元素寬度

[英]React: Can't get correct width of element after render

如果一段文本大於其容器,我正在嘗試在 React 中設置一個選取框,但我無法獲得容器的正確寬度,即使在組件呈現之后也是如此。

我在另一個答案中讀到React “after render” 代碼? 您必須使用我正在嘗試的 requestAnimationFrame 但它仍然無法正常工作。

如果我記錄容器的寬度,它會顯示 147px 的寬度,這是在樣式表中使用 min-width 設置的,但正確的寬度應該是 320px,當屏幕 min-width 為 600px 時,它是使用媒體查詢設置的。

這是一個子組件,如果它有任何不同,父組件會在 iFrame 內呈現,並且 iFrame 的寬度遠遠超過 600px。

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', '');
    }
  }

});

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;
  }
}

我嘗試了許多不同的解決方案,包括layoutreact-component-width-mixin,但它們都不起作用。 我嘗試反應組件寬度混合,因為在我的應用程序的另一部分,我試圖獲取window.innerWidth的值,但在渲染后也會返回 0,除非我設置了大約 2 秒的超時,但不幸的是有時 2 秒不是'由於數據加載和其他回調,時間足夠長,因此可以輕松剎車。

任何幫助都非常感謝。 謝謝。

更新:答案之一正確指出我應該調用this.initMarquee(); 在我正在做的componentDidMount內部,不幸的是我粘貼了錯誤的代碼,我在測試時粘貼了錯誤的代碼,以查看在render調用它是否有所不同。 正確的代碼如下所示:

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

不幸的是,這也不起作用,我仍然收到不正確的 marqueeWrap 寬度。

更新:24/06/2015只是為了澄清,這是我想要實現的選取框效果,僅當文本大於其容器時,因為當它不是更大時滾動它是毫無意義的。

這里還有一個來自 React 團隊的Github 問題的鏈接,它談到了為什么 React 在瀏覽器繪制之前呈現。 - 在這種情況下,我想知道如何可靠地獲得相關元素的寬度。

可能發生的一個問題是,在componentDidMount觸發時,您的CSS尚未加載。 使用webpack可能會發生這種情況,並且即使您的項目中的組件之前已包含css,也將css包含在還包含js的包中。

正如您所指出的,在處理虛擬DOM時存在幾個問題。 您絕對不想嘗試使用jQuery來操縱DOM節點,而React可能會為您的嘗試大喊大叫。

有一個名為React-Context的庫,它將完全滿足您的要求。 您可以將其api公開給包裝器組件,然后能夠偵聽虛擬dom內組件上的事件。

這個庫有點塵土飛揚,但是它應該可以與您共享的代碼示例一起使用。

我對這個問題感到困惑,您要如何處理寬度?

此外,React只是JavaScript,因此您應該能夠在componentDidMount函數上觸發一​​些代碼,該函數在元素在瀏覽器dom中具有物理空間之后執行。 因此,就像任何JavaScript代碼一樣,您將能夠訪問該div並獲取其寬度等。

JavaScript方式...

document.getElementById("mydiv").offsetWidth;

jQuery方式...

$('#mydiv').width();

如果您要解決的問題是動態更改div的寬度,因為它在渲染后看起來不正確,等等...這實際上應該使用CSS來完成。

您不應該調用this.initMarquee(); 在render()方法中。

通常,您根本不應該在render()方法中使用DOM。

嘗試調用this.initMarquee(); componentDidMount方法中。

(在這種情況下,我真的不理解requestAnimationFrame的用法)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM