ReactJS获得渲染的组件高度

时间:2015-07-27 19:37:48

标签: reactjs

我尝试集成或创建https://github.com/kumailht/gridforms的React版本,为此我需要规范化行内部列的高度。原始文件采用网格行的高度并将其应用于子列。

我原本打算获得行的高度,然后将其映射到孩子的属性,虽然从我的尝试中我认为这可能不是理想的方式甚至可能吗?

以下是我目前的代码。

GridRow = React.createClass({
  render(){
        const children = _.map(this.props.children, child => {
            child.props.height = // somehow get row component height
            return child
        })
    return (<div data-row-span={this.props.span} {...this.props}>
      {children}
    </div>)
  }
})

GridCol = React.createClass({
  render(){
    return (<div data-field-span={this.props.span} style={{height:this.props.height}} {...this.props}>
      {this.props.children}
    </div>)
  }
})

我测试过这种方式设置样式并且它会起作用,但是高度不是很高。

编辑:小提琴:

https://jsfiddle.net/4wm5bffn/2/

9 个答案:

答案 0 :(得分:15)

答案有点晚,但从技术上讲,你可以通过这种方式获得元素:

Private Sub DataTable_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
    If e.KeyCode = Keys.Escape Then
        Me.Close()
    End If
End Sub

答案 1 :(得分:11)

根据当前的React文档,refs的首选用法是传递一个回调而不是一个字符串,以便在this.refs的其他地方访问。 所以要获得div的高度(在React.Component类中):

componentDidMount() {
  this.setState({ elementHeight: this.divRef.clientHeight });
}

render() {
  return <div ref={element => this.divRef = element}></div>
}

或者它以这种方式工作,但我不知道这是否可取,因为我们在render方法中设置了状态。

getHeight(element) {
  if (element && !this.state.elementHeight) { // need to check that we haven't already set the height or we'll create an infinite render loop
    this.setState({ elementHeight: element.clientHeight });
  }
}

render() {
  return <div ref={this.getHeight}></div>;
}

参考:https://facebook.github.io/react/docs/more-about-refs.html

答案 2 :(得分:8)

以下是使用refsclientWidth / clientHeight的示例:

import React, { Component } from 'react';
import MyImageSrc from './../some-random-image.jpg'

class MyRandomImage extends Component {
  componentDidMount(){
    let { clientHeight, clientWidth } = this.refs.myImgContainer;
    console.log(clientHeight, clientWidth);
  }
  render() {
    return (
      <div ref="myImgContainer">
        <img src={MyImageSrc} alt="MyClickable" />
      </div>
    );
  }
}

export default MyRandomImage;

注意:这似乎对width可靠,但不是height。如果我找到修复程序,我会编辑...

答案 3 :(得分:7)

不要了解其他任何人,但我总是必须在下一个刻度上得到它,以确保获得正确的高度和宽度。感觉很讨厌,但猜测它与渲染周期有关,但我现在就把它拿走。 onLayout在某些用例中可能会更好。

componentDidMount() {
  setTimeout(() => {
    let ref = this.refs.Container
    console.log(ref.clientHeight)
    console.log(ref.clientWidth)
  }, 1)
}

答案 4 :(得分:1)

根据this answer组件的大小可以在componentDidMount事件处理程序中具有零宽度或高度。所以我看到了一些方法来解决它。

  1. 在顶级React组件上处理事件,并重新计算其中的大小,或重绘特定的子组件。

  2. componentDidMount上设置加载事件处理程序,以处理将单元格加载到react组件中以重新计算正确的大小:

    componentDidMount = () => {
       this.$carousel = $(this.carousel)
       window.addEventListener('load', this.componentLoaded)
    }
    

    然后在componentLoaded方法中执行您需要做的事情。

答案 5 :(得分:0)

我个人的意见是尽量避免使用这样的静态和测量尺寸,因为它可能会使应用程序不必要地复杂化。但有时你无法解决它。您需要先安装组件,然后才能从中获取大小。

一般方法:

  • 为元素提供参考
  • 呈现元素时,请抓住参考号并致电.clientWidth和/或GridRow = React.createClass({ render(){ const children = _.map(this.props.children, child => { child.props.height = // somehow get row component height return child }) return (<div data-row-span={this.props.span} {...this.props}> <GridCol onSizeChange={(size) => { //Set it to state or whatever console.log("sizeOfCol", size); }} /> </div>) } }) GridCol = React.createClass({ componentDidMount(){ //Set stizes to the local state this.setState({ colH: this.col.clientHeight, colW: this.col.clientWidth }); //Use a callback on the props to give parent the data this.props.onSizeChange({colH: this.col.clientHeight, colW: this.col.clientWidth}) } render(){ //Here you save a ref (col) on the class return (<div ref={(col) => {this.col = col}} data-field-span={this.props.span} style={{height:this.props.height}} {...this.props}> <.... > </div>) } })
  • 将值放在状态上或使用props
  • 传递
  • 从状态变量
  • 中渲染需要大小的元素

在您的情况下,您想要获取列的大小,您可以执行以下操作:

 function (link) {
        $.ajax({
            async: true,
            type: "POST",
            url: "ws.asmx/GetServiceDetail",
            data: "{'mainLink':'"+link+"'}",
            contentType: "application/json; charset=utf-8",
            headers: {
                'Cache-Control': 'max-age=1000' 
            },
            dataType: "json",
            success: function (dc, status) {
                var itemImages = dc.itemImages;

                for (var img of itemImages ) {

                    $("#mainSlider").append('<li><img class="img-responsive" src="'+img.ImageLink+'" alt=""></li>');

                    $("#thumbnail").append('<li><img src="' + img.ThumbnailLink + '" alt=""></li>');
                }

                imgSize($(window).width());

答案 6 :(得分:0)

上述解决方案很好。我以为自己会添加自己的内容来帮助我解决此问题,以及其他在此问题中讨论过的问题。

由于其他人已经说过超时功能是不可预测的,并且具有javascript变量依赖性(例如style={{height: `calc(100vh - ${this.props.navHeight}px)`}})的内联css可以在componentDidMount方法之后更改元素的高度,因此必须在更新之后所有元素和内联javascript计算的CSS均已执行。

我无法在React中找到关于哪些元素接受onLoad属性的很好的信息,但是我知道img元素可以。因此,我只是在react组件的底部加载了一个隐藏的图像元素。我使用onLoad在其他地方更新了引用组件的高度,以产生正确的结果。我希望这对其他人有帮助。

_setsectionheights = () => {
    this.setState({
      sectionHeights: [
        this.first.clientHeight,
        this.second.clientHeight,
        this.third.clientHeight,
      ]
    });
}

render() {
    return (
        <>
            <section
            ref={ (elem) => { this.first = elem } }
            style={{height: `calc(100vh - ${this.props.navHeight}px)`}}
            >
                ...
            </section>
            ...
            <img style={{display: "none"}} src={..} onLoad={this._setsectionheights}/>
        </>
    );
}

为了更全面,问题在于执行componentDidMount方法时,它仅考虑外部CSS(此处为推测)。因此,当用clientHeight值引用时,我的section元素(在外部CSS中设置为min-height:400px)每个都返回400。一旦加载完所有内容,img便会简单地更新状态下的剖面高度。

答案 7 :(得分:0)

再晚一点,但是我有一种无需使用getElementById方法就可以使用的方法。可以创建一个基于类的组件,并可以使用示例代码。

constructor(props) {
  super(props);
  this.imageRef = React.createRef();
}

componentDidMount(){
  this.imageRef.current.addEventListener("load", this.setSpans);
}

setSpans = () => {
  //Here you get your image's height
  console.log(this.imageRef.current.clientHeight);
};

render() {
  const { description, urls } = this.props.image;
  return (
    <div>
     <img ref={this.imageRef} alt={description} src={urls.regular} />
    </div>
  );
}

答案 8 :(得分:-1)

我宁愿在componentDidUpdate中执行此操作,但要确保满足条件以防止无限循环:

  componentDidUpdate(prevProps, prevState) {
    const row = document.getElementById('yourId');
    const height = row.clientHeight;
    
    if (this.state.height !== height) {
      this.setState({ height });
    }
  }