Django音乐流媒体网站JS播放异常:点击歌曲始终显示首歌元信息
修复方案:Django音乐网站播放器信息不更新问题
问题场景
开发基于Django的音乐流媒体网站,实现了点击歌曲在统一播放器播放的功能,但点击任意歌曲时,播放器始终显示第一首歌的名称、歌手和封面图片,仅音频播放正常。
现有代码
JavaScript函数
function playSong(element){ var songUrl = element.getAttribute('data-song-url'); var audioPlayer = document.getElementById('audioPlayer'); var audioSource = document.getElementById('audioSource'); audioSource.src = songUrl; audioPlayer.load(); audioPlayer.play(); var songId = element.id; var newImage = document.getElementById("A_" + songId).src; var newSongName = document.getElementById("B_" + songId).textContent; var newArtistName = document.getElementById("C_" + songId).textContent; console.log(newSongName) //always displaying the things of the first song console.log(newImage) console.log(newArtistName) document.getElementById("audio-img").src = newImage; document.getElementById("audio-song").textContent = newSongName; document.getElementById("audio-artist").textContent = newArtistName; }
Django模板HTML
{% for i in songs %} <div class="carousel-cell"> <section class="main_song"> <div class="song-card"> <div class="containera"> <img src="{{i.image}}" id="A_{{i.id}}" alt="song cover"> <div class="overlaya"></div> <div> <a class="play-btn" data-song-url="{{i.song.url}}" id="{{i.id}}" onclick="playSong(this)"><i class="fas fa-play-circle fa-2x"></i></a> {% if user.is_authenticated %} <div class="add-playlist-btn"> <a id="W_{{i.song_id}}" title="Add to Playlist" onclick="showDiv(this)"><i class="fas fa-ellipsis-h"></i></a> </div> {% endif %} </div> </div> </div> <div> <p class="songName" id="B_{{i.id}}">{{i.name}}</p> <p class="artistName" id="C_{{i.id}}">{{i.artist}}</p> </div> </section> </div> {% endfor %}
问题原因
核心问题是依赖ID获取元素的方式存在隐患:要么是循环中生成的id="{{i.id}}"并非唯一值(比如songs中的对象ID重复),要么是DOM中存在多个相同ID的元素,导致getElementById始终返回第一个匹配的元素。
修复方案
推荐两种可靠的修复方式,无需依赖ID:
方案1:通过DOM遍历获取当前歌曲信息
利用closest和querySelector从点击元素的上级节点定位到当前歌曲卡片的信息,避免ID依赖:
function playSong(element){ var songUrl = element.getAttribute('data-song-url'); var audioPlayer = document.getElementById('audioPlayer'); var audioSource = document.getElementById('audioSource'); audioSource.src = songUrl; audioPlayer.load(); audioPlayer.play(); // 定位到当前歌曲的父级卡片容器 var songCard = element.closest('.main_song'); // 从卡片中提取信息 var newImage = songCard.querySelector('.containera img').src; var newSongName = songCard.querySelector('.songName').textContent; var newArtistName = songCard.querySelector('.artistName').textContent; console.log(newSongName); console.log(newImage); console.log(newArtistName); // 更新播放器信息 document.getElementById("audio-img").src = newImage; document.getElementById("audio-song").textContent = newSongName; document.getElementById("audio-artist").textContent = newArtistName; }
方案2:通过Data属性直接传递信息
将歌曲的名称、歌手、封面地址直接存在点击按钮的data-*属性中,直接读取无需DOM遍历:
修改Django模板
{% for i in songs %} <div class="carousel-cell"> <section class="main_song"> <div class="song-card"> <div class="containera"> <img src="{{i.image}}" alt="song cover"> <div class="overlaya"></div> <div> <a class="play-btn" data-song-url="{{i.song.url}}" data-song-name="{{i.name}}" data-artist-name="{{i.artist}}" data-image-url="{{i.image}}" onclick="playSong(this)"> <i class="fas fa-play-circle fa-2x"></i> </a> {% if user.is_authenticated %} <div class="add-playlist-btn"> <a id="W_{{i.song_id}}" title="Add to Playlist" onclick="showDiv(this)"><i class="fas fa-ellipsis-h"></i></a> </div> {% endif %} </div> </div> </div> <div> <p class="songName">{{i.name}}</p> <p class="artistName">{{i.artist}}</p> </div> </section> </div> {% endfor %}
修改JavaScript函数
function playSong(element){ var songUrl = element.getAttribute('data-song-url'); var audioPlayer = document.getElementById('audioPlayer'); var audioSource = document.getElementById('audioSource'); audioSource.src = songUrl; audioPlayer.load(); audioPlayer.play(); // 直接从Data属性读取歌曲信息 var newImage = element.getAttribute('data-image-url'); var newSongName = element.getAttribute('data-song-name'); var newArtistName = element.getAttribute('data-artist-name'); console.log(newSongName); console.log(newImage); console.log(newArtistName); // 更新播放器信息 document.getElementById("audio-img").src = newImage; document.getElementById("audio-song").textContent = newSongName; document.getElementById("audio-artist").textContent = newArtistName; }
内容的提问来源于stack exchange,提问作者Federico Monetti
相关产品推荐
相关产品推荐

