Osc*_*son 329 javascript reactjs
我有一个应用程序,我需要动态设置元素的高度(让我们说"app-content").它需要应用程序的"chrome"的高度并减去它,然后将"app-content"的高度设置为在这些约束内适合100%.这对于vanilla JS,jQuery或Backbone视图来说非常简单,但是我很难弄清楚在React中执行此操作的正确流程是什么?
下面是一个示例组件.我希望能够设置app-content的高度是窗口减去的尺寸为100%ActionBar和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;
Run Code Online (Sandbox Code Playgroud)
Har*_*fer 280
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>
);
}
});
Run Code Online (Sandbox Code Playgroud)
Gra*_*ath 223
使用的一个缺点componentDidUpdate,或者componentDidMount它们实际上是在绘制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 [...]
Run Code Online (Sandbox Code Playgroud)
Ell*_*ong 92
根据我的经验window.requestAnimationFrame,还不足以确保DOM已经完全渲染/重排完成componentDidMount.我运行的代码在componentDidMount调用之后立即访问DOM 并且仅使用window.requestAnimationFrame将导致元素存在于DOM中; 但是,由于尚未发生回流,因此尚未反映元素尺寸的更新.
唯一真正可行的方法是将我的方法包装在a setTimeout和a中,window.requestAnimationFrame以确保在注册下一帧的渲染之前,React的当前调用堆栈被清除.
function onNextFrame(callback) {
setTimeout(function () {
requestAnimationFrame(callback)
})
}
Run Code Online (Sandbox Code Playgroud)
如果我不得不推测为什么会发生/必要,我可以看到React批处理DOM更新,而不是实际应用更改到DOM,直到当前堆栈完成.
最后,如果您在React回调之后使用的代码中使用DOM测量,则可能需要使用此方法.
我觉得这个解决方案很脏,但我们走了:
componentDidMount() {
this.componentDidUpdate()
}
componentDidUpdate() {
// A whole lotta functions here, fired after every render.
}
Run Code Online (Sandbox Code Playgroud)
现在我只是坐在这里等待下来的选票.
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;
Run Code Online (Sandbox Code Playgroud)
另外,有关生命周期反应的更多信息,请查看以下链接:https: //facebook.github.io/react/docs/state-and-lifecycle.html
您可以更改状态,然后在setState回调中进行计算。根据React文档,这“保证在应用更新后会触发”。
这应该在 componentDidMount在代码或其他地方(例如在调整大小事件处理程序上)完成,而不是在构造函数中完成。
这是一个很好的替代方法window.requestAnimationFrame,它不存在某些用户在此处提到的问题(需要将其组合setTimeout或多次调用)。例如:
class AppBase extends React.Component {
state = {
showInProcess: false,
size: null
};
componentDidMount() {
this.setState({ showInProcess: true }, () => {
this.setState({
showInProcess: false,
size: this.calculateSize()
});
});
}
render() {
const appStyle = this.state.showInProcess ? { visibility: 'hidden' } : null;
return (
<div className="wrapper">
...
<div className="app-content" style={appStyle}>
<List items={items} />
</div>
...
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
只是使用新的Hook方法来更新此问题,您可以简单地使用useEffect钩子:
import React, { useEffect } from 'react'
export default function App(props) {
useEffect(() => {
// your post layout code (or 'effect') here.
...
},
// array of variables that can trigger an update if they change. Pass an
// an empty array if you just want to run it once after component mounted.
[])
}
Run Code Online (Sandbox Code Playgroud)
另外,如果要在布局安装之前运行,请使用useLayoutEffect钩子:
import React, { useLayoutEffect } from 'react'
export default function App(props) {
useLayoutEffect(() => {
// your pre layout code (or 'effect') here.
...
}, [])
}
Run Code Online (Sandbox Code Playgroud)
小智 6
实际上,有比使用请求动画帧或超时更简单、更清晰的版本。我很惊讶没有人提出这个问题:vanilla-js onload 处理程序。如果可以,请使用组件确实挂载,如果不能,只需在 jsx 组件的 onload 处理程序上绑定一个函数。如果您希望该函数运行每个渲染,也请在渲染函数中返回结果之前执行它。代码如下所示:
runAfterRender = () =>
{
const myElem = document.getElementById("myElem")
if(myElem)
{
//do important stuff
}
}
render()
{
this.runAfterRender()
return (
<div
onLoad = {this.runAfterRender}
>
//more stuff
</div>
)
}Run Code Online (Sandbox Code Playgroud)
}
我遇到了同样的问题。
在大多数情况下,使用hack-ish是可行setTimeout(() => { }, 0)的componentDidMount()。
但不是特殊情况;而且我不想使用,ReachDOM findDOMNode因为文档中说:
注意:findDOMNode是用于访问基础DOM节点的转义口。在大多数情况下,不建议使用此逃生阴影,因为它会穿透组件抽象。
(来源: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);
}
Run Code Online (Sandbox Code Playgroud)
然后:
componentDidUpdate() {
this.updateDimensions();
}
Run Code Online (Sandbox Code Playgroud)
最后,就我而言,我必须删除在中创建的侦听器componentDidMount:
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimensions.bind(this));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
257891 次 |
| 最近记录: |