反应“渲染后”的代码?

我有一个应用程序,我需要设置一个元素的高度(可以说“应用程序内容”)dynamic。 它需要应用程序的“chrome”的高度,然后减去它,然后将“app-content”的高度设置为在这些约束内适合100%。 这是超级简单的与香草JS,jQuery,或骨干的意见,但我很努力找出什么是正确的过程将在React做到这一点?

以下是一个示例组件。 我希望能够将app-content的高度设置为窗口的100%减去ActionBarBalanceBar的大小,但是如何知道什么时候渲染了一切,以及将计算内容放在这个React类中?

 /** @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; 

https://facebook.github.io/react/docs/react-component.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> ); } }); 

使用componentDidUpdatecomponentDidMount一个缺点是,它们在dom元素完成绘制之前实际执行,但是在它们从React传递到浏览器的DOM之后。

举例来说,如果你需要将node.scrollHeight设置为呈现的node.scrollTop,那么React的DOM元素可能不够。 您需要等到元素完成绘制才能获得高度。

解:

使用requestAnimationFrame确保您的代码在绘制新渲染的对象后运行

 scrollElement: function() { //store a this ref, and var _this = this; //wait for a paint to do scrolly stuff window.requestAnimationFrame(function() { var node = _this.getDOMNode(); if (node !== undefined) { //and scroll them! node.scrollTop = node.scrollHeight; } }); }, componentDidMount: function() { this.scrollElement(); }, // and or componentDidUpdate: function() { this.scrollElement(); }, // and or render: function() { this.scrollElement() return [...] 

根据我的经验, window.requestAnimationFrame不足以确保DOM已经从componentDidMount完全呈现/回stream完成。 我有代码运行,在componentDidMount调用后立即访问DOM,并且只使用window.requestAnimationFrame会导致元素出现在DOM中; 然而,由于还没有发生回stream,元件尺寸的更新尚未反映出来。

唯一真正可靠的工作方式是将我的方法封装在setTimeoutwindow.requestAnimationFrame以确保React的当前调用堆栈在注册下一帧的渲染之前被清除。

 function onNextFrame(callback) { setTimeout(function () { window.requestAnimationFrame(callback) }, 0) } 

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

最终,如果您在Reactcallback之后使用的代码中使用DOM测量,则可能需要使用此方法。

从ReactDOM.render()文档:

如果提供了可选的callback函数,则在组件被呈现或更新后将执行callback。

我觉得这个解决scheme很肮脏,但是在这里我们去:

 componentDidMount() { this.componentDidUpdate() } componentDidUpdate() { // A whole lotta functions here, fired after every render. } 

现在我正要坐在这里等候倒票。

渲染之后,可以像下面那样指定高度,并可以指定相应反应组件的高度。

 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指定每个反应组件的高度。 指定前2个反应组件的主div的固定宽度,然后用自动指定第三个组件的主div的高度。 所以根据第三个div的内容来分配高度。

实际上我遇到了类似的问题,我使用id属性渲染了一个Component中的video元素,所以当RenderDOM.render()结束时,它会加载一个需要id的插件来find占位符,并且找不到它。

componentDidMount()中的0ms的setTimeout固定:)

 componentDidMount() { if (this.props.onDidMount instanceof Function) { setTimeout(() => { this.props.onDidMount(); }, 0); } } 

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组件生命周期方法: https : //facebook.github.io/react/docs/react-component.html#the-component-lifecycle

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

  • componentWillUnmount() – 组件即将从浏览器DOM中移除

我遇到了同样的问题。

在使用componentDidMount()的hack-ish setTimeout(() => { }, 0)大多数场景中都是有效的。

但不是特例; 我不想使用ReachDOM findDOMNode因为文档说:

注意:findDOMNode是一个用于访问底层DOM节点的逃生舱口。 在大多数情况下,使用这个逃生舱口是不鼓励的,因为它刺穿了组件的抽象。

(来源: https : //facebook.github.io/react/docs/react-dom.html#finddomnode )

所以在那个特定的组件中,我不得不使用componentDidUpdate()事件,所以我的代码就像这样:

 componentDidMount() { // feel this a little hacky? check this: http://stackoverflow.com/questions/26556436/react-after-render-code setTimeout(() => { window.addEventListener("resize", this.updateDimensions.bind(this)); this.updateDimensions(); }, 0); } 

接着:

 componentDidUpdate() { this.updateDimensions(); } 

最后,在我的情况下,我不得不删除在componentDidMount创build的监听器:

 componentWillUnmount() { window.removeEventListener("resize", this.updateDimensions.bind(this)); } 

React在这些情况下有很less的生命周期方法,包括但不限于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; 

关于生命周期的更多信息,请参考下面的链接: https : //facebook.github.io/react/docs/state-and-lifecycle.html

getInitialState,getDefaultProps,componentWillMount,componentDidMount