'YT' 未定义 - Youtube 播放器 API
'YT' is not defined - Youtube Player API
我在我的 React 网站上使用 Youtube Player API。当我在网站上尝试时,它给出了这个错误:TypeError: Cannot read property 'ready' of undefined
。这是我使用的代码:
var player;
function loadVideo() {
window.YT.ready(function () {
new window.YT.Player("player", {
height: "390",
width: "640",
videoId: "M7lc1UVf-VE",
events: {
onReady: onPlayerReady,
onStateChange: onPlayerStateChange,
},
});
});
function onPlayerReady(event) {
event.target.playVideo();
player = event.target;
}
function onPlayerStateChange(event) {
var videoStatuses = Object.entries(window.YT.PlayerState);
console.log(videoStatuses.find((status) => status[1] === event.data)[0]);
}
}
useEffect(() => {
setMaxDuration("06:00");
var tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
loadVideo();
}, []);
iframe:
<div id="player">
<iframe
title="p"
id="player"
width="560"
height="315"
src="https://www.youtube.com/embed/sGPrx9bjgC8&autoplay=1"
frameBorder="0"
allowFullScreen
></iframe>
</div>
(将代码编辑为最新的解决方法)
我怎样才能让它工作?
您必须按照 documentation 的建议加载库。下面的代码异步加载库,然后库在准备就绪时通过全局 onYouTubeIframeAPIReady
回调(名称是必需的)“回调”您的代码。
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
console.log('Yay, YT exists!', YT);
}
在 YouTube 库代码中进行一些逆向工程时,我们可以看到这一行(我自己未缩小):
const callback = window.onYouTubeIframeAPIReady;
callback && callback();
显示了该函数是如何被调用的,以及为什么它不存在时不会抛出任何错误。
当我再次阅读您的问题时,您使用的是 React,因此之前的解决方案可能无法很好地集成,您可能不希望使用全局回调而改用它:
const useYoutube = callback => {
useEffect(() => {
if (!window.YT) {
var tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
tag.onload = callback;
} else {
callback();
}
}, []);
};
这个自定义挂钩只会延迟加载 YouTube 库一次(第一次需要加载)。您可以在每个需要它的组件中导入它,并与 useYoutube(loadVideo)
.
一起使用
这是一个有效的Stackblitz demo
也适用于本地:
对象出现在控制台中的原因是控制台与您的代码异步运行。当你有错误时 YT is not yet loaded, but it has been by the time the console is displayed.
您可以证明这是更改控制台日志以使用 JSON.serialise() 将对象解析为字符串,然后将记录对象的运行时状态。
我在我的 React 网站上使用 Youtube Player API。当我在网站上尝试时,它给出了这个错误:TypeError: Cannot read property 'ready' of undefined
。这是我使用的代码:
var player;
function loadVideo() {
window.YT.ready(function () {
new window.YT.Player("player", {
height: "390",
width: "640",
videoId: "M7lc1UVf-VE",
events: {
onReady: onPlayerReady,
onStateChange: onPlayerStateChange,
},
});
});
function onPlayerReady(event) {
event.target.playVideo();
player = event.target;
}
function onPlayerStateChange(event) {
var videoStatuses = Object.entries(window.YT.PlayerState);
console.log(videoStatuses.find((status) => status[1] === event.data)[0]);
}
}
useEffect(() => {
setMaxDuration("06:00");
var tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
loadVideo();
}, []);
iframe:
<div id="player">
<iframe
title="p"
id="player"
width="560"
height="315"
src="https://www.youtube.com/embed/sGPrx9bjgC8&autoplay=1"
frameBorder="0"
allowFullScreen
></iframe>
</div>
(将代码编辑为最新的解决方法) 我怎样才能让它工作?
您必须按照 documentation 的建议加载库。下面的代码异步加载库,然后库在准备就绪时通过全局 onYouTubeIframeAPIReady
回调(名称是必需的)“回调”您的代码。
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onYouTubeIframeAPIReady() {
console.log('Yay, YT exists!', YT);
}
在 YouTube 库代码中进行一些逆向工程时,我们可以看到这一行(我自己未缩小):
const callback = window.onYouTubeIframeAPIReady;
callback && callback();
显示了该函数是如何被调用的,以及为什么它不存在时不会抛出任何错误。
当我再次阅读您的问题时,您使用的是 React,因此之前的解决方案可能无法很好地集成,您可能不希望使用全局回调而改用它:
const useYoutube = callback => {
useEffect(() => {
if (!window.YT) {
var tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
tag.onload = callback;
} else {
callback();
}
}, []);
};
这个自定义挂钩只会延迟加载 YouTube 库一次(第一次需要加载)。您可以在每个需要它的组件中导入它,并与 useYoutube(loadVideo)
.
这是一个有效的Stackblitz demo
也适用于本地:
对象出现在控制台中的原因是控制台与您的代码异步运行。当你有错误时 YT is not yet loaded, but it has been by the time the console is displayed.
您可以证明这是更改控制台日志以使用 JSON.serialise() 将对象解析为字符串,然后将记录对象的运行时状态。