我有一个应用程序,我需要动态设置一个元素的高度(让我们说“app-content”)。它取应用程序的“chrome”的高度并减去它,然后设置“app-content”的高度以100%符合这些限制。这是超级简单的香草JS, jQuery,或骨干视图,但我努力弄清楚正确的过程将在React中这样做?

下面是一个示例组件。我想要能够设置应用内容的高度为窗口的100%减去动作栏和BalanceBar的大小,但我怎么知道什么时候所有的渲染和哪里我将把计算的东西在这个反应类?

/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
  render: function () {
    return (
      <div className="wrapper">
        <Sidebar />
        <div className="inner-wrapper">
          <ActionBar title="Title Here" />
          <BalanceBar balance={balance} />
          <div className="app-content">
            <List items={items} />
          </div>
        </div>
      </div>
    );
  }
});

module.exports = AppBase;

当前回答

用ES6类代替React.createClass进行了一点更新

import React, { Component } from 'react';

class SomeComponent extends Component {
  constructor(props) {
    super(props);
    // this code might be called when there is no element avaliable in `document` yet (eg. initial render)
  }

  componentDidMount() {
    // this code will be always called when component is mounted in browser DOM ('after render')
  }

  render() {
    return (
      <div className="component">
        Some Content
      </div>
    );
  }
}

另外,检查React组件生命周期方法:组件生命周期

每个组件都有很多类似componentDidMount的方法。

componentWillUnmount() -组件即将从浏览器DOM中删除

其他回答

当我需要打印接收大量数据的react组件并在画布上绘制时,我遇到了奇怪的情况。我已经尝试了所有提到的方法,它们都不可靠地为我工作,与requestAnimationFrame内setTimeout我得到空画布在20%的时间,所以我做了以下工作:

nRequest = n => range(0,n).reduce(
(acc,val) => () => requestAnimationFrame(acc), () => requestAnimationFrame(this.save)
);

基本上我做了一个requestAnimationFrame的链,不确定这是好主意还是不好,但这在100%的情况下为我到目前为止(我使用30作为n变量的值)。

在我的经验窗口。requestAnimationFrame不足以确保DOM已经从componentDidMount完全渲染/ reflow-complete。我有代码运行,访问DOM后立即componentDidMount调用和使用单独的窗口。requestAnimationFrame将导致元素出现在DOM中;然而,对元素尺寸的更新还没有反映出来,因为回流还没有发生。

唯一真正可靠的方法是将我的方法包装在一个setTimeout和一个窗口中。requestAnimationFrame以确保React的当前调用堆栈在注册下一帧渲染之前被清除。

function onNextFrame(callback) {
    setTimeout(function () {
        requestAnimationFrame(callback)
    })
}

如果我不得不推测为什么这是发生的/必要的,我可以看到React批处理DOM更新,直到当前堆栈完成后才实际应用更改到DOM。

最终,如果你在React回调后触发的代码中使用DOM度量,你可能会想要使用这个方法。

React在这些情况下有一些生命周期方法,列表包括但不限于getInitialState, getDefaultProps, componentWillMount, componentDidMount等。

在你的情况和需要与DOM元素交互的情况下,你需要等待直到DOM准备好,所以使用componentDidMount如下:

/** @jsx React.DOM */
var List = require('../list');
var ActionBar = require('../action-bar');
var BalanceBar = require('../balance-bar');
var Sidebar = require('../sidebar');
var AppBase = React.createClass({
  componentDidMount: function() {
    ReactDOM.findDOMNode(this).height = /* whatever HEIGHT */;
  },
  render: function () {
    return (
      <div className="wrapper">
        <Sidebar />
        <div className="inner-wrapper">
          <ActionBar title="Title Here" />
          <BalanceBar balance={balance} />
          <div className="app-content">
            <List items={items} />
          </div>
        </div>
      </div>
    );
  }
});

module.exports = AppBase;

此外,有关react生命周期的更多信息,您可以查看下面的链接: https://facebook.github.io/react/docs/state-and-lifecycle.html

componentDidMount ()

此方法在呈现组件后调用一次。你的代码应该是这样的。

var AppBase = React.createClass({
  componentDidMount: function() {
    var $this = $(ReactDOM.findDOMNode(this));
    // set el height and width etc.
  },

  render: function () {
    return (
      <div className="wrapper">
        <Sidebar />
          <div className="inner-wrapper">
            <ActionBar title="Title Here" />
            <BalanceBar balance={balance} />
            <div className="app-content">
              <List items={items} />
          </div>
        </div>
      </div>
    );
  }
});

渲染之后,你可以像下面这样指定高度,并可以为相应的react组件指定高度。

render: function () {
    var style1 = {height: '100px'};
    var style2 = { height: '100px'};

   //window. height actually will get the height of the window.
   var hght = $(window).height();
   var style3 = {hght - (style1 + style2)} ;

    return (
      <div className="wrapper">
        <Sidebar />
        <div className="inner-wrapper">
          <ActionBar style={style1} title="Title Here" />
          <BalanceBar style={style2} balance={balance} />
          <div className="app-content" style={style3}>
            <List items={items} />
          </div>
        </div>
      </div>
    );`
  }

或者你可以使用sass指定每个react组件的高度。指定前2个react组件主div的固定宽度,然后第三个组件主div的高度为auto。因此,根据第三个div的内容,高度将被分配。