如何为多个生成的元素设置 on.click?

How do I set up an on.click for multiple generated elements?

作为一个学生项目,我们正在尝试建立一个提供电影推荐的网站。生成推荐后,我们希望用户能够单击任何电影海报以提取有关该特定电影的更多信息。 .on('click') 当前 selects 所有不理想的结果...

目前我们拥有的是:

axios.get(omdbCall + movieTitles)
  .then(function(response){

  let movies = response.data.results;

  for (i=0; i < movies.length; i++) {
     var posterPath = movies[i].poster_path;
     var movieID = movies[i].id;
     var movTitle = movies[i].title;
     var movImg = "https://image.tmdb.org/t/p/w92";

     $('#movPoster').append('<img class="posters" src=' + movImg + posterPath + '>');
   }

     $(".posters").on("click", function () {
        console.log("I clicked a poster!");
     })
})

我们还尝试更改呈现的 img 标签以包含基于电影标题或其 imdbID 的 ID。我们尝试使用此 selector 进行两次尝试:

$("#" + movTitle)

在附加函数中进行此更改:

$('#movPoster').append('<img id=' + movTitle + ' src=' + movImg + posterPath + '>');

我希望能够 select 只有一个元素,但事实并非如此。我希望我解释得当并且足够详细。任何帮助将不胜感激。谢谢!

您正在对动态生成的 html 进行 .on('click') 事件直接处理。这行不通。因为最初加载脚本时,没有 class posters.

的元素

你必须使用这样的东西

$("#not_dynamic_element").on("click", ".posters", function(){
 // Code here
});

逻辑是您必须 select 一个未动态加载的元素。即,作为 posters class 的祖先的静态元素。

例如,假设您有一个 div 和 class posters-container,它在页面加载时已经存在。您正在将带有 class postersimg 标签附加到此 div。所以你需要点击所有带有 class postersimg 标签,你可以写,

$(".posters-container").on("click", ".posters", function(){
 // Code here
});

希望您理解逻辑和问题所在。

更新 - FIDDLE

中的逻辑问题

我看到你的 fiddle 出了什么问题。我试图让它变得简单。所以检查你写的这段代码

axios.get(finalSearch)
    .then(function(response){
        // console.log(response);
        let movies = response.data.Similar.Results;
        // let posters = response.data.results.poster_path;
        for (i=0; i < movies.length; i++){
            // console.log(movies[i].Name);
            var movArr = movies[i].Name;
            var movStr = movArr.split(" ");
            var movieTitles = movStr.join("+")
            getMoviePosters(movieTitles);
        }         
    })
    .catch(function(err) {
        console.log(err);
    })

在此代码中,您可以看到您在 for 循环内调用函数 getMoviePosters(movieTitles)。您的 for 循环包含用于 select 动态生成的电影海报元素的以下行。

$("#movPoster").on("click", function () {
    console.log("I clicked a poster!");             
})

所以我建议你在 for 循环之后调用这个点击函数,如下所示(删除之前的代码)。同时添加postersclass点击功能

axios.get(finalSearch).then(function(response){
    // console.log(response);
    let movies = response.data.Similar.Results;
    // let posters = response.data.results.poster_path;
    for (i=0; i < movies.length; i++){
        // console.log(movies[i].Name);
        var movArr = movies[i].Name;
        var movStr = movArr.split(" ");
        var movieTitles = movStr.join("+")
        getMoviePosters(movieTitles);
    }
    $("#movPoster").on("click", '.posters', function () {
        console.log("I clicked a poster!");             
    })
})

原因

可能当代码$(".posters").on("click",...) 运行时 img.posters#movPoster 仍未在 html.So 中呈现,点击事件未触发。

解决方案

  • 您可以尝试将您的代码移动到$(function() { // move your codes here });(related question!) 内,或者在$(".posters").on("click",...) 之前添加console.log($('#movPoster'), $('#movPoster .posters')) 以验证目标元素是否存在.
  • 并将点击事件绑定到#movPoster而不是img.posters

建议

为了更好的性能,您应该重构您的代码:

  • 将点击事件绑定到 #movPoster 而不是 img.posters,这会使事件侦听器过多时的性能变差。

  • 循环中的代码$('#movPoster').append(element)会导致不必要的重绘,因为每个循环都会在#movPoster 中插入元素。你可以这样重写它:

var dom = '';
for(var i=0; i<3; i++) {
 dom += '<img src="">'
}
$('#movPoster').append(dom) // only insert dom 1 time, not 3 times