onclick事件传递函数参数提示“未定义”问题排查
解决Watchlist添加按钮onclick传参未定义/异常问题
问题描述
我在开发「添加到收藏清单(Watchlist)」功能时遇到两个问题:
- 初始代码中,点击按钮触发
onclick事件时,传递的data.imdbID参数提示「未定义」 - 尝试用
slice(2)移除imdbID开头的tt前缀后,点击按钮出现异常结果
原代码
HTML代码
<html> <head> <link rel="stylesheet" href="index.css"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet"> </head> <body> <div class="container"> <header> <div class="head"> <h1>Find your film</h1> <a href="#">My Watchlist</a> </div> <div class="search-bar"> <i class="fa-solid fa-magnifying-glass icon"></i> <input type="text" class="input-field" id="input-text"> <button type="submit" class="submit" id="submit-btn">Search</button> </div> </header> <main id="body-container"></main> </div> <script src="index.js"></script> <script src="https://kit.fontawesome.com/a7b56fbb1c.js" crossorigin="anonymous"></script> </body> </html>
初始JS代码
const body = document.getElementById("body-container") const watchlistBtn = document.getElementsByClassName("add-watchlist") let watchlist = [] document.getElementById("submit-btn").addEventListener("click", function() { let searchValue = document.getElementById("input-text").value let arr = [] fetch(`https://www.omdbapi.com/?i=tt3896198&apikey=f2f47683&type=movie&s=${searchValue}`) .then(res => res.json()) .then(data => { for (let i = 0; i < data.Search.length; i++) { arr.push(data.Search[i].imdbID) } for (let item of arr) { fetch(`https://www.omdbapi.com/?apikey=f2f47683&i=${item}`) .then(res => res.json()) .then(data => { renderMovie(data) }) } }) }) function renderMovie(data) { body.innerHTML += ` <div class="list-container"> <div class="movie-container"> <img src="${data.Poster}" class="poster"> <div class="movie-details"> <div class="row-1"> <h2 id="movie-title">${data.Title}</h2> <i class="fa-solid fa-star"></i> <p id="movie-rating">${data.imdbRating}</p> </div> <div class="row-2"> <p id="run-time">${data.Runtime}</p> <p id="genre">${data.Genre}</p> <div id="button-container"> <button class="add-watchlist" onclick="addToWatchlist(${data.imdbID})"><i class="fa-solid fa-plus"></i> Watchlist</button> </div> </div> <p class="description">${data.Plot}</p> </div> </div> </div> ` } function addToWatchlist(dataID) { watchlist.push(dataID) console.log(dataID) }
修改后的JS代码(出现异常的版本)
function renderMovie(data) { let numb = data.imdbID.slice(2) body.innerHTML += ` <div class="list-container"> <div class="movie-container"> <img src="${data.Poster}" class="poster"> <div class="movie-details"> <div class="row-1"> <h2 id="movie-title">${data.Title}</h2> <i class="fa-solid fa-star"></i> <p id="movie-rating">${data.imdbRating}</p> </div> <div class="row-2"> <p id="run-time">${data.Runtime}</p> <p id="genre">${data.Genre}</p> <div id="button-container"> <button class="add-watchlist" onclick="addToWatchlist(${numb})"><i class="fa-solid fa-plus"></i> Watchlist</button> </div> </div> <p class="description">${data.Plot}</p> </div> </div> </div> ` } function addToWatchlist(dataID) { watchlist.push(dataID) console.log(dataID) }
问题原因
- 初始代码的「未定义」问题:
data.imdbID是字符串类型(如tt123456),直接写在模板字符串的onclick中时,渲染后的HTML会变成onclick="addToWatchlist(tt123456)"。浏览器会把tt123456当作变量名而非字符串,因未定义该变量而报错。 - 修改后异常问题:用
slice(2)得到的是数字开头的字符串(如123456或007),渲染后变成onclick="addToWatchlist(007)"。JS会把带前导零的数字当作八进制数解析,导致ID值错误(比如007会被解析为7);同时我们需要的是字符串类型的ID,而非数字类型。
解决方案
方案1:给参数添加引号(快速修复)
在模板字符串中给data.imdbID包裹单引号,让浏览器识别为字符串:
function renderMovie(data) { body.innerHTML += ` <div class="list-container"> <div class="movie-container"> <img src="${data.Poster}" class="poster"> <div class="movie-details"> <div class="row-1"> <h2 id="movie-title">${data.Title}</h2> <i class="fa-solid fa-star"></i> <p id="movie-rating">${data.imdbRating}</p> </div> <div class="row-2"> <p id="run-time">${data.Runtime}</p> <p id="genre">${data.Genre}</p> <div id="button-container"> <!-- 给参数添加单引号 --> <button class="add-watchlist" onclick="addToWatchlist('${data.imdbID}')"><i class="fa-solid fa-plus"></i> Watchlist</button> </div> </div> <p class="description">${data.Plot}</p> </div> </div> </div> ` }
方案2:使用事件委托(更健壮)
内联onclick不利于代码维护,推荐用事件委托绑定事件,避免字符串解析问题:
const body = document.getElementById("body-container") let watchlist = [] // 保留搜索逻辑,修改renderMovie函数移除onclick,添加data-id属性 document.getElementById("submit-btn").addEventListener("click", function() { let searchValue = document.getElementById("input-text").value let arr = [] fetch(`https://www.omdbapi.com/?i=tt3896198&apikey=f2f47683&type=movie&s=${searchValue}`) .then(res => res.json()) .then(data => { for (let i = 0; i < data.Search.length; i++) { arr.push(data.Search[i].imdbID) } for (let item of arr) { fetch(`https://www.omdbapi.com/?apikey=f2f47683&i=${item}`) .then(res => res.json()) .then(data => { renderMovie(data) }) } }) }) function renderMovie(data) { body.innerHTML += ` <div class="list-container"> <div class="movie-container"> <img src="${data.Poster}" class="poster"> <div class="movie-details"> <div class="row-1"> <h2 id="movie-title">${data.Title}</h2> <i class="fa-solid fa-star"></i> <p id="movie-rating">${data.imdbRating}</p> </div> <div class="row-2"> <p id="run-time">${data.Runtime}</p> <p id="genre">${data.Genre}</p> <div id="button-container"> <!-- 添加data-id存储imdbID --> <button class="add-watchlist" data-id="${data.imdbID}"><i class="fa-solid fa-plus"></i> Watchlist</button> </div> </div> <p class="description">${data.Plot}</p> </div> </div> </div> ` } // 事件委托绑定点击事件 body.addEventListener('click', function(e) { const targetBtn = e.target.closest('.add-watchlist'); if(targetBtn) { const dataID = targetBtn.dataset.id; watchlist.push(dataID); console.log(dataID); } })
内容的提问来源于stack exchange,提问作者mohammed shajahan
相关产品推荐
相关产品推荐

