2014-03-06 86 views
9

我綁在組件的根DOM元素的中間定位一個圓圈:React.js:參考文獻並非適用於初次呈現

var App = React.createClass({ 
    render: function() { 
     return <svg ref="svg"> 
      <circle r="9" cx={this.centerX()} cy="15"/> 
     </svg>; 
    }, 
    centerX: function() { 
     var svg = this.refs.svg.getDOMNode(); 
     return svg.offsetLeft + Math.round(svg.offsetWidth/2); 
    } 
}); 

http://jsfiddle.net/NV/94tCQ/

雞還是先有蛋的問題發生在這裏:this.refs在第一個渲染中未定義。解決這個問題的最好方法是什麼?我不想引用外部DOM節點(如document.body)。

回答

17

這並不是說refs沒有定義,那就是你想在你試圖生成它同時訪問DOM。 this.refs.svg.getDOMNode不會返回任何內容,因爲組件在render中沒有真正的DOM表示。

爲了保持更多的陣營-Y,我會提出cx到組件的狀態和更新的元素已被渲染到DOM後:

var App = React.createClass({ 
    componentDidMount: function() { 
     var svg = this.refs.svg.getDOMNode(); 
     this.setState({ 
      cx: svg.offsetLeft + Math.round(svg.offsetWidth/2) 
     }); 
    }, 
    getInitialState: { 
     return { 
      cx: 0 
     }; 
    }, 
    render: function() { 
     return (
      <svg ref="svg"> 
       <circle r="9" cx={this.state.cx} cy="15" /> 
      </svg> 
     ); 
    } 
}); 
+2

當然,如果您知道svg元素的尺寸,您也可以計算渲染中的適當中心以避免必須從DOM讀取數據。在這種情況下,它不會特別明顯,但對於性能來說,最好避免從DOM讀取並儘可能重新渲染。 –

+0

@BenAlpert好點。雖然在這種情況下代碼引用了'offsetLeft',這是相對於DOM節點的最近位置父親。直到offsetParent和this元素都已呈現給DOM,才能獲得該數字。這可能會更好地解決在CSS中,但這似乎是最合適的原始文章中的代碼。 –

+1

我完全同意。我的評論主要針對原始海報,作爲可選的增強功能。 –

2

解決這個問題的方法是在DOM尚未插入的時候返回一個虛擬值,當它使用componentDidMount(然後重新繪製元素)。

centerX: function() { 
     if (!this.refs || !this.refs.svg) { 
      return 0; 
     } 
     var svg = this.refs.svg.getDOMNode(); 
     return svg.offsetLeft + Math.round(svg.offsetWidth/2); 
    }, 
    componentDidMount: function() { 
     this.forceUpdate(); 
    } 

http://jsfiddle.net/vjeux/94tCQ/4/

+1

這看起來的確哈克。 :) –