点击Font Awesome图标播放音频时Jinja循环仅触发首个音频如何解决
问题根源
- 你在Jinja循环中给所有audio元素设置了重复的
id="content",HTML规范要求页面ID必须全局唯一,document.getElementById只会返回页面中第一个匹配ID的元素,因此所有点击事件最终都触发第一个音频的播放。 - 你将
playContent函数和audio变量的定义放在循环内,每次循环都会覆盖全局的audio变量和playContent函数,最终全局作用域内只会保留最后一次循环定义的内容,进一步导致逻辑异常。
修复后的代码
将公共JS逻辑提取到循环外部,点击时通过DOM节点关系直接获取对应音频元素,无需依赖ID绑定:
{% extends "layout.html" %} {% block content %} <legend class="border-bottom mb-4">All Posts</legend> <!-- 公共JS只需定义一次,不要放在循环内重复加载 --> <script> function playContent(clickIcon) { // 获取点击图标同级的audio元素 const targetAudio = clickIcon.nextElementSibling; targetAudio.play(); } </script> {% for post in posts %} <article class="media content-section"> <div> <!-- 点击时将当前图标元素作为参数传入函数 --> <i class="fas fa-volume-up" onclick="playContent(this)" style="color: blue;"></i> <!-- 移除重复的id属性 --> <audio> <source src="link-to-blob-storage/{{ post.ttsFileName }}" type="audio/mp3"> </audio> </div> </article> {% endfor %} {% endblock content %}
可选优化
你可以额外添加全局状态控制,实现点击新音频时自动暂停上一个正在播放的音频,避免多个音频同时播放:
// 全局变量存储当前正在播放的音频实例 let currentPlaying = null; function playContent(clickIcon) { const targetAudio = clickIcon.nextElementSibling; // 暂停上一个正在播放的音频 if (currentPlaying && currentPlaying !== targetAudio) { currentPlaying.pause(); currentPlaying.currentTime = 0; } // 切换当前音频的播放状态 if (targetAudio.paused) { targetAudio.play(); currentPlaying = targetAudio; } else { targetAudio.pause(); targetAudio.currentTime = 0; currentPlaying = null; } }
内容的提问来源于stack exchange,提问作者Darren_D19
相关产品推荐
相关产品推荐

