问题已修复,代码已更新
将 youtubeReady Promise 放入另一个文件 (youtubeReady.js) 并从中导入:
const YTReady = new Promise( (resolve) => {
window.onYouTubeIframeAPIReady = () => resolve(window.YT);
});
export default YTReady;
代码更新标记文件
帖子更新:
我已经根据 HMR 的回答尝试了可能的解决方案。
但是没用...
(以下代码也已更新)
我替换原来的代码:
this.player = new Promise (...)
this.player.then(...)
采用新方法
const youtubeReady = new Promise(...)
youtubeReady.then(...)
结果是视频甚至没有出现在 firstCmp 和 secondCmp 类对象(构造函数)中。
我在这两个组件的 componentDidMount() 中使用了 console.log(this),但没有加载任何视频。
我做对了吗?或者我错过了什么?
原始帖子内容
好吧,最近几天我解决了之前的问题,通过 mouseOver/mouseLeave 事件让 Youtube-api 工作。
现在我遇到了一个新问题,我为此苦苦挣扎了 2 天。
我有 3 个组件。
先设置脚本标签获取api(app.js):
import React, {Component} from "react";
import ReactDom from "react-dom";
import './app.scss';
import FirstCmp from './firstCmp.js'
import secondCmp from './secondCmp.js'
class App extends Component {
componentDidMount() {
let tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
let firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
}
render() {
return (
<div id="app">
<FirstCmp />
<SecondCmp />
</div>
)
}
}
ReactDom.render(<App/>, document.getElementById('root'))
然后创建一个视频(firstCmp.js):
import React, { Component } from 'react';
import style from './firstCmp.scss';
import YTReady from './resource/youtubeReady';
export default class FirstCmp extends Component {
constructor(props) {
super(props);
// just for example, not real code
this.state = {
iframeId: "myIframe",
src: "src"
}
}
componentDidMount() {
let youtubeReady = YTReady;
youtubeReady.then( (YT) => {
this.player = new YT.Player(this.state.iframeId, {
events: {
'onReady': () => this.onPlayerReady(),
'onStateChange': () => this.onPlayerStateChange()
}
})
})
}
mouseOver() {
this.player.playVideo();
}
mouseLeave() {
this.player.pauseVideo();
}
render() {
return (
<section className={style.firstCmpContent}>
<iframe
id={this.state.iframeId}
src={`${this.state.src}`}
frameBorder="0"
style={style.firstCmp}
onMouseOver={ () => this.mouseOver() }
onMouseLeave={ () => this.mouseLeave() } >
</iframe>
</section>
);
}
}
到目前为止一切顺利。第一个视频效果很好。 直到我创建第二个视频...(secondCmp.js)
import React, { Component } from "react";
import style from './secondCmp.scss';
import YTReady from './resource/youtubeReady';
export default class SecondCmp extends Component {
constructor(props) {
super(props);
// just for example, not real code
this.state = {
iframeId: "myIframe",
src: "src"
}
}
componentDidMount() {
let youtubeReady = YTReady;
youtubeReady.then( (YT) => {
this.player = new YT.Player(iframeId, {
events: {
'onReady': () => this.onPlayerReady(),
'onStateChange': () => this.onPlayerStateChange()
}
})
})
}
mouseOver() {
this.player.playVideo();
}
mouseLeave() {
this.player.pauseVideo();
}
render() {
return (
<section className={style.secondCmpContent}>
<iframe
id={this.state.iframeId}
src={`${this.state.src}`}
frameBorder="0"
style={style.secondCmp}
onMouseOver={ () => this.mouseOver() }
onMouseLeave={ () => this.mouseLeave() } >
</iframe>
</section>
);
}
}
现在,只有第二个视频有效,第一个视频获得待定 promise !
如果我创建第三个视频,那么第二个和第一个视频将获得待定 promise 只有新的(第三个)在工作,依此类推。
我该如何解决这个问题?
最佳答案
创建一个全局 promise ,因为 onYouTubeIframeAPIReady
在加载脚本时被调用并且应该只发生一次,之后每次都会准备好 you can find a similar question here .目前,您每次都使用不同的函数覆盖 onYouTubeIframeAPIReady
。
所以你可以有一个 promise 或服务(不是每个组件一个):
const youtubeReady = new Promise( (resolve) => {
window.onYouTubeIframeAPIReady = () => resolve(window.YT);
});
然后在你的组件中:
youtubeReady.then( (YT) => {
this.player = new YT.Player(iframeId, {//not sure where iframeId comes from
events: {
'onReady': () => this.onPlayerReady(),
'onStateChange': () => this.onPlayerStateChange()
}
})
})
关于javascript - 使用多个 iframe vids 的 ReactJS 只有 1 个有效,其他是 Promise pending,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49749300/