2015-06-22 94 views
2

我想建立一個大帳篷中作出反應,如果某一段文字是比它更大的容器,但我不能讓容器的正確寬度,即使在該組件已呈現。陣營:無法獲取元素的正確寬度渲染後

我在另一個答案React 「after render」 code?閱讀,你必須使用requestAnimationFrame,我正在嘗試,它仍然無法正常工作。

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

這是一個子組件,父被呈現在iframe內,如果這有什麼差別和iframe的寬度超過600像素。

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

我已經嘗試了許多不同的解決方案,包括laidoutreact-component-width-mixin,但他們都沒有工作。我嘗試了反應組件寬度mixin,因爲在我的應用程序的另一部分,我試圖獲得window.innerWidth的值,但是在渲染後也會返回0,除非我設置了約2秒的超時時間,不幸的是儘管有時2秒不長足夠的數據加載和其他回調,所以這可以很容易地制動。

任何幫助真的很感激。謝謝。

更新: 答案之一正確地指出,我應該叫this.initMarquee();componentDidMount這是我在做什麼,不幸的是我貼的時候我測試,看它是否由內render差異調用它的錯誤代碼。正確的代碼如下所示:

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

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

更新:24/06/2015 只是爲了澄清,這是marquee effect我想實現的,只有當文本比它的容器作爲大是沒有意義的滾動它時,它並不是越大。

而且,這裏是從陣營團隊談到爲何做出反應器油漆之前呈現給Github Issue的鏈接。 - 因此,我想知道如何可靠地獲取有問題的元素的寬度。

+0

我不是100%清楚你的目標是什麼。你想保持你的內容溢出一個容器?你遇到的問題是什麼? – badAdviceGuy

+0

不,我希望我的內容在其容器大於其容器時自動水平滾動,如類似於選框效果,類似於此http://jsfiddle.net/jonathansampson/xxuxd/ –

回答

0

我對這個問題的困惑,究竟是你想用的寬度呢?

這且不說,REACT爲只有JavaScript,因此,你應該能夠開槍的元素在你的瀏覽器的DOM物理空間之後執行的componentDidMount功能的一些代碼。因此,就像任何JavaScript代碼,你將能夠訪問該分區,並得到它的寬度等等

JavaScript的方式...

document.getElementById("mydiv").offsetWidth; 

jQuery的方法...

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

如果你正在試圖解決的是動態變化的一個div的寬度,因爲它不看它的渲染之後等方面的問題..這應該使用CSS來完成。

+0

感謝您的迴應Chris。所有我想要做的寬度是告訴一個元素是否比它的容器大。如果它比我想要應用類更大,以便滾動文本進出其容器尺寸,就像選取框效果一樣。不幸的是,JavaScript方式或jQuery方式都不起作用,因爲React在瀏覽器繪製DOM之前呈現元素,因爲它們不會返回正確的寬度,正如此處所述 - http://stackoverflow.com/questions/26556436/react-after -render-code –

+0

而且可能是因爲我對要獲取寬度的元素有媒體查詢。它在媒體查詢應用之前返回值。 –

+0

我不太明白。 componentDidMount在元素位於dom後被調用。現在,如果你引用另一個尚未加載的元素,那將是我唯一能想到的。 –

0

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

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

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

(我真不明白的​​在這種情況下使用)

+0

感謝您收到@ByScripts - 您是正確的,我已經設置了這種方式,不幸的是它沒有工作。正如鏈接的答案中所述,使用requestAnimationFrame是因爲:「使用componentDidUpdate或componentDidMount的一個缺點是它們在dom元素完成繪製之前實際執行,但是在它們從React傳遞到瀏覽器的DOM之後。「 –

1

有幾個問題,如你所指出的,在處理虛擬DOM。你絕對不想試圖用jQuery來操作DOM節點,而且React可能會在你嘗試的時候尖叫。

有一個名爲React-Context的庫,它可以完全符合你的要求。你會將它的api暴露給你的包裝器組件,然後能夠聽到虛擬dom中的組件上的事件。

這個庫有點灰塵,但它應該與你共享的代碼示例一起工作。

+0

感謝您的更新@newswim。我現在不再積極工作,但您的解決方案聽起來真的很有趣!如果我再次回到工作,我會實施您的解決方案並報告回來。 –

2

可能發生的一個可能的問題是,當componentDidMount觸發時,您的CSS尚未加載。這可能發生在webpack中,並且在你的包中包含也包含你的js的CSS,即使你已經在你的組件之前在項目中包含了CSS。