“YT”未定义 - Youtube 播放器 API

Aji*_*mar 0 javascript iframe reactjs youtube-iframe-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();
  }, []);
Run Code Online (Sandbox Code Playgroud)

内嵌框架:

  <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>
Run Code Online (Sandbox Code Playgroud)

(将代码编辑为最​​新的解决方法)我怎样才能让它工作?

Twi*_*her 5

您必须按照文档的建议加载该库。下面的代码异步加载库,然后库在准备好时通过全局回调“回调”您的代码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);
}
Run Code Online (Sandbox Code Playgroud)

在 YouTube 库代码中进行一些逆向工程时,我们可以看到这一行(我自己未缩小):

const callback = window.onYouTubeIframeAPIReady;
callback && callback();
Run Code Online (Sandbox Code Playgroud)

它显示了如何调用该函数以及为什么它不存在时不会抛出任何错误。


当我再次阅读你的问题时,你正在使用 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();
    }
  }, []);
};
Run Code Online (Sandbox Code Playgroud)

这个自定义挂钩只会惰性地加载 YouTube 库一次(第一次需要时)。您可以将其导入到每个需要它的组件中,并将其与useYoutube(loadVideo).

这是一个有效的Stackblitz 演示

也适用于本地: 在此输入图像描述