如果一段文本大于其容器,我试图在React中设置Marquee,但即使在组件渲染后我也无法获得正确的容器宽度。
我在另一个答案React “after render” code?中读到你必须使用我正在尝试的requestAnimationFrame并且它仍然无效。
如果我记录容器的宽度,则显示宽度为147px,使用样式表中的min-width设置,但正确的宽度应为320px,当屏幕最小宽度为600px时,使用媒体查询设置该宽度。
这是一个子组件,如果父组件有任何差异且iFrame的宽度超过600px,则父组件将在iFrame中呈现。
JS:
module.exports = React.createClass({
componentDidUpdate: function () {
// Setup marquee
this.initMarquee();
},
render: function () {
// Setup marquee
this.initMarquee();
var artistName = this.props.artist.artistName;
var trackName = this.props.track.trackName;
return (
<div className="MV-player-trackData no-select" ref="mvpTrackData">
<div className="MV-player-trackData-marquee-wrap" ref="mvpMarqueeWrap">
<div className="MV-player-trackData-marquee" ref="mvpMarquee">
<a className="MV-player-trackData-link no-select" href={this.props.storeUrl} target="_blank">
<span id="mvArtistName">{artistName}</span> – <span id="mvTrackName">{trackName}</span>
</a>
</div>
</div>
</div>
)
},
initMarquee: function () {
if ( typeof requestAnimationFrame !== 'undefined' ) {
//store a this ref, and
var self = this;
//wait for a paint to setup marquee
window.requestAnimationFrame(function() {
self.marquee();
});
}
else {
// Suport older browsers
window.setTimeout(this.marquee, 2000);
}
},
marquee: function () {
var marquee = React.findDOMNode(this.refs.mvpMarquee);
var marqueeWrap = React.findDOMNode(this.refs.mvpMarqueeWrap);
// If the marquee is greater than its container then animate it
if ( marquee.clientWidth > marqueeWrap.clientWidth ) {
marquee.className += ' is-animated';
}
else {
marquee.className = marquee.className.replace('is-animated', '');
}
}
});
CSS:
.MV-player-trackData-marquee-wrap {
height: 20px;
line-height: 20px;
min-width: 147px;
overflow: hidden;
position: relative;
width: 100%;
@media only screen and (min-width : 600px) {
min-width: 320px;
}
}
我尝试了许多不同的解决方案,包括laidout和react-component-width-mixin,但它们都不起作用。我试过反应组件宽度mixin,因为在我的应用程序的另一部分我尝试获取window.innerWidth
的值,但在渲染后也返回0,除非我设置超时约2秒,不幸的是有时候由于数据加载和其他回调,2秒还不够长,因此可以轻松制动。
非常感谢任何帮助。感谢。
更新
其中一个答案正确地指出我应该在我this.initMarquee();
内调用componentDidMount
,不幸的是我在测试时粘贴了错误的代码,看看它是否在内部调用{{1} 1}}。正确的代码如下所示:
render
不幸的是,这也不起作用,我仍然收到marqueeWrap的错误宽度。
更新:2015年6月24日 只是为了澄清,这是我试图实现的marquee effect,只有当文本比容器更大时才会实现,因为当它不大时,它会毫无意义地滚动它。
此处还有来自React团队的Github Issue链接,说明了React在浏览器绘制之前呈现的原因。 - 所以在这种情况下,我想知道如何可靠地获得有问题元素的宽度。
答案 0 :(得分:3)
可能出现的一个问题是,当componentDidMount触发时,您的CSS尚未加载。这可能发生在webpack中,包括你的包中也包含你的js的css,即使你已经在项目中的组件之前包含了css。
答案 1 :(得分:1)
正如您已经指出的,在处理虚拟DOM时有几个问题。你绝对不想尝试使用jQuery来操纵DOM节点,而且React可能会因你的尝试而尖叫。
有一个名为React-Context的图书馆可以完全按照您的要求行事。您可以将其api公开给您的包装器组件,然后能够侦听虚拟dom中组件上的事件。
这个库有点尘土飞扬,但它应该与您共享的代码示例一起使用。
答案 2 :(得分:0)
我对这个问题感到困惑,你想用宽度做什么?
除此之外,React只是JavaScript,因此您应该能够在componentDidMount函数上触发一些代码,该函数在元素在浏览器dom中具有物理空间之后执行。因此,就像任何JavaScript代码一样,您将能够访问该div并获得它的宽度等......
JavaScript方式......
document.getElementById("mydiv").offsetWidth;
jQuery方式......
$('#mydiv').width();
如果您要解决的问题是动态更改div的宽度,因为它在渲染后看起来不正确......这应该是使用CSS完成的。
答案 3 :(得分:0)
您不应该在render()方法中调用this.initMarquee();
。
通常,您不应在render()
方法中使用DOM。
尝试使用this.initMarquee();
方法调用componentDidMount
。
(我真的不明白在这种情况下使用requestAnimationFrame
)