JS动态生成音乐列表 歌曲时长仅第一行生效问题
问题原因
- 选择器查找范围错误:循环中每次调用
tbody.querySelector(".audio_duration")时,querySelector只会返回匹配规则的第一个DOM元素,也就是列表第一行的时长单元格。无论循环到第几首歌,拿到的永远是第一行的元素,所以所有时长计算结果都被写入了第一行,其余行的时长单元格从未被修改。 - 音频路径硬编码:创建
Audio实例时固定传入了audio/1.mp3,即使修复选择器问题,所有行显示的也会是同一个音频的时长,无法和当前行的歌曲对应。
修复方案
只需要调整两处逻辑即可:
- 每次插入新行后,只在当前刚插入的行范围内查找时长单元格,不要从整个tbody全局查找。
- 将Audio对象的音频路径替换为当前循环项对应的歌曲路径,不要硬编码固定文件名。
修复后的完整循环代码如下:
// 创建音乐列表 const tbody = document.querySelector("tbody"); // 根据歌曲数组长度生成对应行 for (let i = 0; i < songs.length; i++) { // 读取当前歌曲信息拼接行模板 let trTag = `<tr tr-index = ${i}> <td class="numberlist" width="5%">${songs[i].nmbr}</td> <td class="title" width="80%"> <div> <img class="cover1" src=${songs[i].coverPath} > </div> <div class="songdetails"> <h3>${songs[i].trackName}</h3> <h4>${songs[i].trackArtist}</h4> </div> </td> <td width="30%"> <h4>${songs[i].trackAlbum}</h4> </td> <td width="15%">${songs[i].date}</td> <td width="5%"> <img class="svg1" src="/assets/asset 72.svg" alt=""> </td> <td width="12%" class="audio_duration">0:00</td> </tr> `; tbody.insertAdjacentHTML("beforeend", trTag); // 取刚插入的最新一行,仅在当前行内查找时长元素 const currentRow = tbody.lastElementChild; let trAudioDuration = currentRow.querySelector(".audio_duration"); // 替换为当前歌曲对应的音频路径,不要硬编码固定文件名 let trAudioTag = new Audio(songs[i].audioPath); trAudioTag.addEventListener("loadeddata", () => { let aDuration = trAudioTag.duration; let totalMin = parseInt(aDuration / 60); let totalSec = parseInt(aDuration % 60); if (totalSec < 10) { totalSec = `0${totalSec}`; }; trAudioDuration.innerHTML = `${totalMin}:${totalSec}`; }); };
注:代码中
songs[i].audioPath需要替换为你自己songs数组中存储音频文件路径的实际字段名。
问题复现效果

内容的提问来源于stack exchange,提问作者Mayank Bhadana
相关产品推荐
相关产品推荐

