在刺激框架中从 API 访问惰性全局变量
Accessing lazy global variable from API in stimulus framework
我正在尝试创建一个 Stimulus controller which would access global Youtube Player API 变量
Youtube Player API 延迟加载 - class 加载 异步
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
问题是,Stimulus 不想访问 YT 变量。
我尝试创建一个加载脚本的函数,然后运行给定的函数,并将其导入到 stimulus
export function loadScript (url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) { // only required for IE <9
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function () {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
但是如您所见,它只是创建了新的脚本对象,所以 Stimulus 仍然无法访问它。
有没有办法让 Stimulus 访问加载的脚本以及其中声明的变量?
这是一个完整的控制器代码(不要介意不好的做法,这只是一个快速尝试):
import {
Controller
} from 'stimulus';
import $ from 'jquery';
export default class extends Controller {
static targets = ['collapseButton', 'player']
connect() {
this.initPlayer();
}
initPlayer() {
let player = $('#youtubePlayer');
// Code taken straight from https://developers.google.com/youtube/iframe_api_reference?hl=pl
player = new YT.Player(player, {
videoId: 'Va297erJjJ4',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
function onPlayerReady(event) {
event.target.playVideo();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
}
}
<div class="youtube-player-modal" data-controller="youtubeplayer">
<div id="youtubePlayer"></div>
</div>
我这里写了一个解决你的问题的方法,那里你必须先调用ready函数,然后再给回调。
https://codesandbox.io/s/funny-browser-n3m3j?file=/src/Player.js
// loadScript.js
import Player from "./Player";
function loadScript(url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) {
// only required for IE <9
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
callback();
}
};
} else {
//Others
script.onload = function () {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
loadScript("https://www.youtube.com/iframe_api", new Player().initPlayer);
// Player.js
import { Controller } from "stimulus";
import $ from "jquery";
export default class extends Controller {
static targets = ["collapseButton", "player"];
connect() {
this.initPlayer();
}
initPlayer() {
let player = $("#youtubePlayer");
window.YT.ready(function () {
player = new window.YT.Player("youtubePlayer", {
height: "360",
width: "640",
videoId: "Va297erJjJ4",
events: {
onReady: onPlayerReady,
onStateChange: onPlayerStateChange
}
});
});
function onPlayerReady(event) {
event.target.playVideo();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data === window.YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div
class="youtube-player-modal"
data-controller="youtubeplayer"
>
<div id="youtubePlayer"></div>
</div>
<script src="src/loadScript.js"></script>
</body>
</html>
我正在尝试创建一个 Stimulus controller which would access global Youtube Player API 变量
Youtube Player API 延迟加载 - class 加载 异步
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
问题是,Stimulus 不想访问 YT 变量。
我尝试创建一个加载脚本的函数,然后运行给定的函数,并将其导入到 stimulus
export function loadScript (url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) { // only required for IE <9
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function () {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
但是如您所见,它只是创建了新的脚本对象,所以 Stimulus 仍然无法访问它。
有没有办法让 Stimulus 访问加载的脚本以及其中声明的变量?
这是一个完整的控制器代码(不要介意不好的做法,这只是一个快速尝试):
import {
Controller
} from 'stimulus';
import $ from 'jquery';
export default class extends Controller {
static targets = ['collapseButton', 'player']
connect() {
this.initPlayer();
}
initPlayer() {
let player = $('#youtubePlayer');
// Code taken straight from https://developers.google.com/youtube/iframe_api_reference?hl=pl
player = new YT.Player(player, {
videoId: 'Va297erJjJ4',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
function onPlayerReady(event) {
event.target.playVideo();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
}
}
<div class="youtube-player-modal" data-controller="youtubeplayer">
<div id="youtubePlayer"></div>
</div>
我这里写了一个解决你的问题的方法,那里你必须先调用ready函数,然后再给回调。 https://codesandbox.io/s/funny-browser-n3m3j?file=/src/Player.js
// loadScript.js
import Player from "./Player";
function loadScript(url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState) {
// only required for IE <9
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
callback();
}
};
} else {
//Others
script.onload = function () {
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
loadScript("https://www.youtube.com/iframe_api", new Player().initPlayer);
// Player.js
import { Controller } from "stimulus";
import $ from "jquery";
export default class extends Controller {
static targets = ["collapseButton", "player"];
connect() {
this.initPlayer();
}
initPlayer() {
let player = $("#youtubePlayer");
window.YT.ready(function () {
player = new window.YT.Player("youtubePlayer", {
height: "360",
width: "640",
videoId: "Va297erJjJ4",
events: {
onReady: onPlayerReady,
onStateChange: onPlayerStateChange
}
});
});
function onPlayerReady(event) {
event.target.playVideo();
}
var done = false;
function onPlayerStateChange(event) {
if (event.data === window.YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
}
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div
class="youtube-player-modal"
data-controller="youtubeplayer"
>
<div id="youtubePlayer"></div>
</div>
<script src="src/loadScript.js"></script>
</body>
</html>