You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将fetch获取的数据传入反引号模板字符串内的onclick函数

问题原因

报错由两个问题共同导致:

  • 代码存在笔误:entlet list = ""; 为拼写错误,需修正为 let list = "";
  • 核心逻辑错误:在模板字符串中直接将JS对象song插值到内联onclick属性时,对象会被默认转换为字符串[object Object],最终渲染出的事件代码为makeAllplays([object Object]),不符合JS语法规范,浏览器解析时就会抛出Unexpected identifier错误。

解决方案

推荐优先使用事件委托的方式处理动态生成元素的点击事件,避免内联事件的转义、作用域问题,代码可维护性更强:

方案1:事件委托(推荐)

  1. 修正笔误,渲染DOM时给每个歌曲项添加存储歌曲唯一标识(数组索引/歌曲ID)的自定义属性,移除内联onclick绑定:
const res = await fetch('./songApi/songs.json')
const fetchedSongs = await res.json()
let list = "";
// 单纯做遍历拼接不需要用map,forEach语义更合适
fetchedSongs.forEach((song, index) => {
  list += `
    <div class="songitem" style="background:${song.background} ;" data-song-index="${index}">
    <img src="${song.coverpath}" alt="${song.SongName}">
    <span class="name">${song.SongName}</span>
    <span class="songlistplay">
    <span class="songTime">${song.time}</span>
    <i class="far fa-play-circle songitemplay"></i>
    </span>
    </div>`
})
// 将拼接完成的列表插入到页面对应容器,示例容器class为song-list-wrap
document.querySelector('.song-list-wrap').innerHTML = list
  1. 给歌曲列表的父容器绑定一次点击事件,通过事件委托匹配播放按钮,拿到对应歌曲数据后调用播放逻辑:
// 父容器绑定点击事件,后续动态新增的歌曲项也能生效
document.querySelector('.song-list-wrap').addEventListener('click', (e) => {
  // 判断点击目标是否为播放按钮
  if (e.target.classList.contains('songitemplay')) {
    // 向上查找最近的歌曲项元素,读取存在自定义属性上的索引
    const songItem = e.target.closest('.songitem')
    const songIndex = Number(songItem.dataset.songIndex)
    // 拿到对应歌曲数据
    const currentSong = fetchedSongs[songIndex]
    // 执行播放逻辑
    makeAllplays(currentSong)
  }
})

// 播放函数正常接收歌曲对象参数即可
function makeAllplays(song) {
  console.log('当前播放歌曲:', song)
  // 补充你的播放逻辑
}

方案2:内联事件传参(不推荐,易出现转义bug)

如果一定要保留内联onclick写法,不能直接传入对象,可传入歌曲索引/ID作为唯一标识,在函数内部回查完整歌曲数据:

fetchedSongs.forEach((song, index) => {
  list += `
    <div class="songitem" style="background:${song.background} ;">
    <img src="${song.coverpath}" alt="${song.SongName}">
    <span class="name">${song.SongName}</span>
    <span class="songlistplay">
    <span class="songTime">${song.time}</span>
    <i class="far fa-play-circle songitemplay" onClick="makeAllplays(${index})" ></i>
    </span>
    </div>`
})

// 对应函数修改为接收索引参数
function makeAllplays(songIndex) {
  const currentSong = fetchedSongs[songIndex]
  // 补充播放逻辑
}

注意:如果尝试直接传入JSON序列化后的对象,必须手动转义引号,否则会破坏HTML属性结构,兼容性很差,非必要不使用该写法。


额外优化点
  • 插值到HTML属性的变量必须包裹引号,比如src="${song.coverpath}",如果路径包含空格、特殊字符会导致属性解析错误
  • 图片alt属性不要写死固定值,替换为当前歌曲名song.SongName更符合可访问性规范
  • 没有返回值需求的遍历操作不要用map,map是用来生成新数组的方法,单纯做遍历拼接用forEach或普通for循环更合理

内容的提问来源于stack exchange,提问作者Rohit Barate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 12:51:19