对React较新;我有一个父组件,它使用react-youtube组件从1-6个youtube视频中生成任意位置。想法是YouTube
组件将根据数组中的youtube视频ID动态生成。目前,我正在生成类似
{this.state.videoIds.map((videoId, index) =>
<YouTube
key={index}
opts={opts}
videoId={videoId}
onReady={this._onReady} />
)}
就生成组件而言,它按预期工作。但是,问题是,当this.state.videoIds
被更新时,它将导致所有YouTube
组件被刷新。这种行为对我来说很有意义。
我遇到的问题如下:如果功能保持不变,我需要一种方法来跟踪每个YouTube
组件播放器的时间,以便在刷新时可以通过刷新数据时,这些数据会返回到组件,以便可以从中断的位置开始播放。
所以我的问题是,有没有一种方法可以动态生成这些组件而无需刷新所有现有组件?
对于它的价值,我曾考虑过只拥有一个父组件,该组件将为每个用例静态添加组件,但这似乎很笨拙,我真的不想走那条路。
这很有意义,我根据给定时间加载的播放器数量平均分配屏幕空间,代码如下:
calculateVideoWidth = () => {
if (this.state.videoIds.length <= 3) {
return (document.body.clientWidth - 15) / this.state.videoIds.length;
} else {
return (document.body.clientWidth - 15) / this.MAX_NUMBER_OF_COLUMNS;
}
};
calculateVideoHeight = () => {
if (this.state.videoIds.length <= 3) {
return window.innerHeight - 4;
} else {
return (window.innerHeight - 4) / this.MAX_NUMBER_OF_ROWS;
}
};
在我的渲染方法中,我正在执行以下操作:
let opts = {
height: this.calculateVideoHeight(),
width: this.calculateVideoWidth()
};
在查看@Tholle的评论后,我发现“重新加载”来自于调整大小。我想这是有道理的。必须有更好的方法来做到这一点?
查看此链接以查看我遇到的情况:Video App。在输入框中,只需添加一个视频ID(以“,”分隔)。
答案 0 :(得分:0)
此代码可以帮助您从用户离开的任何地方开始视频。
问题是,无论用户离开哪里,我们都需要维护或存储视频的最后播放状态,其中一些状态在重载时永久不可擦除,因此这里使用localStorage
来实现。
import React from "react";
import ReactDOM from "react-dom";
import YouTube from "react-`enter code here`youtube";
class App extends React.Component {
state = {
videoIds: ["2g811Eo7K8U"],
videosPlayState: {}
};
componentDidMount() {
let videosPlayState = localStorage.getItem("videosPlayState") || "{}";
this.setState({
videosPlayState: JSON.parse(videosPlayState)
});
}
addVideo = () => {
this.setState(prevState => ({
videoIds: [...prevState.videoIds, "9kBACkguBR0"]
}));
};
_onStateChange = (event, videoId) => {
let newPlayState = { ...this.state.videosPlayState
};
newPlayState[videoId] = event.target.getCurrentTime();
localStorage.setItem("videosPlayState", JSON.stringify(newPlayState));
};
_onReady(event, videoId) {
event.target.seekTo(this.state.videosPlayState[videoId] || 0);
}
render() {
const opts = {
height: "200",
width: "400",
playerVars: {
autoplay: 1
}
};
return ( <
div className = "App" >
<
div className = "video-container" > {
this.state.videoIds.map((videoId, index) => ( <
YouTube onStateChange = {
event => {
this._onStateChange(event, videoId);
}
}
onReady = {
event => {
this._onReady(event, videoId);
}
}
key = {
index
}
videoId = {
videoId
}
opts = {
opts
}
className = {
"item"
}
/>
))
} <
/div> <
div >
<
button onClick = {
this.addVideo
} > Add video < /button> <
/div> <
/div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
这是CSS:
.video-container .item {
padding: 25px;
display: inline-block;
}
.video-container {
display: flex;
flex-wrap: wrap;
}
以下链接可能会帮助您enter link description here
答案 1 :(得分:0)
更多地使用flexbox之后,我得以解决此问题。我结束了以下内容:
html, body, #root, #root > div, div.container, iframe {
width: 100%;
height: 100%;
margin: 0;
}
div.container {
display: flex;
flex-wrap: wrap;
}
span {
flex-basis: 33%;
flex-grow: 1;
}
作为参考,这是我的jsx
<div>
<div className="container">
{this.state.videoIds.map((videoId, index) =>
<YouTube
id="flex-item"
key={index}
videoId={videoId}
onStateChange={this._onStateChange}
onReady={this._onReady}/>
)}
</div>
</div>
我认为可以用flexbox做到这一点,但是我还没有想出解决方案。我希望这可以帮助其他人。