我目前很难专注于没有像jQuery和co这样的框架的vanilla JavaScript。不幸的是,我知道在最后几天心理上令我不安的两个错误。我已经在互联网上搜索了,但我认为这些错误实际上太过个人化,而不是找到一般的解决方案或在网上工作。
这是我的index.htlml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Songs</title>
</head>
<body>
<div id="body-inner">
<div class="playlist"></div> <br>
<div class="song">
<div class="current"></div> <br>
<span class="time"></span>
<button class="play">Play</button>
<button class="pause">Pause</button>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
这是我的main.js:
const [playlistOut, currentOut, timeOut] = [
document.querySelector(".playlist"),
document.querySelector(".current"),
document.querySelector(".time")
];
// Create the App Object
let app = {
playlists: {
playlistSongs: [
"Backseat",
"Unforgettable",
"BlueSkies",
"Thunder",
"Overflow",
"Up&Down",
"DoMyThing",
"Heroes",
"Miracles",
"CakeByTheOcean",
"InTheEnd",
"Feel"
]
},
songDurations: {
Backseat: 195,
Unforgettable: 252,
BlueSkies: 323,
Thunder: 182,
Overflow: 249,
UpDown: 154,
DoMyThing: 534,
Heroes: 420,
Miracles: 236,
CakeByTheOcean: 379,
InTheEnd: 231,
Feel: 432
},
start: () => {
showPlaylist(app.playlists.playlistSongs);
clickSong();
}
};
window.onload = app.start;
let test = {
minutes: false,
seconds: false
};
// Configure Timer
function startTimer(duration, display) {
var timer = duration,
minutes,
seconds;
if (duration != isNaN) {
var timer = duration,
minutes,
seconds;
interval = setInterval(() => {
minutes = parseInt(timer / 60, 10);
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.textContent = minutes + ":" + seconds;
test.minutes = minutes;
test.seconds = seconds;
console.log("Minutes Func: " + minutes);
console.log("Seconds Func: " + seconds);
if (--timer < 0) {
timer = 0;
}
}, 1000);
} else {
var error = "The given duration is not a number.";
console.log(error);
alert(error);
}
console.log("Inside Func: " + minutes);
return { success: true, min: minutes, secs: seconds };
}
console.log("test.minutes: " + test.minutes);
console.log("test.seconds: " + test.seconds);
// Init Timer
let timerfunc = startTimer(60, timeOut);
console.log(timerfunc.min);
// Manage Play and Pause Buttons
document.querySelector(".pause").addEventListener("click", () => {
clearInterval(interval);
});
document.querySelector(".play").addEventListener("click", () => {
let currentDuration = timerfunc.min * 60 + timerfunc.secs;
console.log(currentDuration);
startTimer(currentDuration, timeOut);
});
// Show Playlist
function showPlaylist(playlist) {
if (playlist.length > 0) {
var constructor = {
content: new Array()
};
for (var i = 0; i < playlist.length; i++) {
constructor.content.push(
'<a href="#" id="' +
playlist[i] +
'" class="song">' +
playlist[i] +
"</a><br>"
);
}
playlistOut.innerHTML = constructor.content.join("");
return true;
} else {
var error = "There is no playlist existing with this name.";
console.log(error);
return false;
}
}
// Get the Time of the Element Clicked and Start the Timer
/* FIXME FIXME FIXME
songElements[i] returns undefined in l. 109 ff.
FIXME FIXME FIXME */
function clickSong() {
var songElements = document.querySelectorAll(".song");
for (var i = 0; i < songElements.length; i++) {
songElements[i].addEventListener("click", function(e) {
e.preventDefault;
console.log(songElements[i].id);
var songDuration = app.songDurations.songElements[i].id;
startTimer(songDuration, timeOut);
currentOut.innerHTML = "Currently Playing: " + songElements[i].id;
});
}
}
正如您所看到的,该应用程序是一个歌曲播放列表,您应该能够从播放列表中动态选择一首歌曲,并能够手动启动和停止歌曲。不幸的是,第53行的函数startTimer()并没有返回所需的值,因此脚本可以在用户再次手动停止后获取当前时间(以秒为单位)启动计时器。我已经用一堆console.log来修改代码,以便更好地理解变量的范围,但我仍然无法解决问题。
可以在clickSong()函数内的第133行找到下一个更重要的错误。我在那里获得了.song类的所有元素并将它们返回到节点列表中。在下一个回合中,我通过所述节点列表运行for循环,以在单击的excact元素上应用单击eventHandler。但是已经出现了问题:我无法点击该项目,实际上for循环第136行的当前迭代始终返回undefined。我遗憾地根本不知道如何解决这个问题。
您是否有想法或者您是否遇到类似情况?如果有帮助,我很高兴。
提前谢谢你,J0nny
答案 0 :(得分:1)
问题是,在任何点击事件触发回调之前,您的i
变量将达到for
循环的结束值。因此,无论发生哪个点击事件,回调都会使用超出范围的i
值。
您可以使用let
代替var
轻松解决此问题,因为这会为每次迭代创建一个新的变量实例,并且那个实例将在异步回调中引用。
for (let i = 0; i < songElements.length; i++) {
此表达式中出现第二个问题:
app.songDurations.songElements[i].id
您的app.songDurations
对象没有songElements
属性,因此无效。你打算这个吗?
app.songDurations[songElements[i].id]
答案 1 :(得分:1)
我改变了很多,所以只需尝试查看代码并查看更改内容
HTML
SELECT mi.*, group_concat(mc.contents)
FROM move_items mi LEFT JOIN
move_contents mc
ON mi.boxnumber = mc.box
GROPU BY mi.boxnumber
ORDER BY mi.date DESC;
JAVASCRIPT
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Songs</title>
</head>
<body>
<div id="body-inner">
<div class="playlist"></div> <br>
<div class="controls">
<div class="current"></div> <br>
<span class="time"></span>
<button class="play">Play</button>
<button class="pause">Pause</button>
</div>
</div>
<script src="main.js"></script>
</body>
</html>
请注意,在我将const [playlistOut, currentOut, timeOut] = [
document.querySelector(".playlist"),
document.querySelector(".current"),
document.querySelector(".time")
];
// Create the App Object
let app = {
playList: [
"Backseat",
"Unforgettable",
"BlueSkies",
"Thunder",
"Overflow",
"Up&Down",
"DoMyThing",
"Heroes",
"Miracles",
"CakeByTheOcean",
"InTheEnd",
"Feel"
],
songDurations: {
Backseat: 195,
Unforgettable: 252,
BlueSkies: 323,
Thunder: 182,
Overflow: 249,
UpDown: 154,
DoMyThing: 534,
Heroes: 420,
Miracles: 236,
CakeByTheOcean: 379,
InTheEnd: 231,
Feel: 432
},
start: () => {
renderPlayList(app.playList);
clickSong();
}
};
window.onload = app.start;
let [playListInterval, currentMinute, currentSecond] = [0, 0, 0];
// Configure Timer
function startTimer(duration, display) {
currentMinute = parseInt(duration / 60, 10);
currentSecond = parseInt(duration % 60, 10);
if (!isNaN(duration)) {
let timer = duration;
playListInterval = setInterval(() => {
currentMinute = parseInt(timer / 60, 10);
currentSecond = parseInt(timer % 60, 10);
const minutes = currentMinute < 10 ? "0" + currentMinute : currentMinute;
const seconds = currentSecond < 10 ? "0" + currentSecond : currentSecond;
display.textContent = minutes + ":" + seconds;
if (--timer < 0) {
timer = 0;
}
}, 1000);
} else {
const error = "The given duration is not a number.";
console.log(error);
alert(error);
}
}
// Manage Play and Pause Buttons
document.querySelector(".pause").addEventListener("click", () => {
if (playListInterval !== 0) {
clearInterval(playListInterval);
playListInterval = 0;
}
});
document.querySelector(".play").addEventListener("click", () => {
let currentDuration = currentMinute * 60 + currentSecond;
startTimer(currentDuration, timeOut);
});
// Show Playlist
function renderPlayList(playlist) {
if (playlist.length > 0) {
const content = [];
for (let i = 0; i < playlist.length; i++) {
content.push(
'<a href="#" id="' +
playlist[i] +
'" class="song">' +
playlist[i] +
"</a><br>"
);
}
playlistOut.innerHTML = content.join("");
return true;
} else {
const error = "There is no playlist existing with this name.";
console.log(error);
return false;
}
}
// Get the Time of the Element Clicked and Start the Timer
function clickSong() {
const songElements = document.querySelectorAll(".song");
for (let i = 0; i < songElements.length; i++) {
const currentElement = songElements[i];
currentElement.addEventListener("click", function (event) {
event.preventDefault();
const songDuration = app.songDurations[currentElement.id];
if (playListInterval !== 0) {
clearInterval(playListInterval);
playListInterval = 0;
}
startTimer(songDuration, timeOut);
currentOut.innerHTML = "Currently Playing: " + currentElement.id;
});
}
}
更改为<div class="song">
的html中,当我尝试播放/暂停时,它告诉我它不是持续时间,因为它具有相同的eventListener作为歌曲列表