简体   繁体   中英

Closures with dynamically generated content

I'm trying to generate an event listener for every element created dynamically. The problem is in the createDisplay function. I'm constantly receiving some errors. I read that the solutions are the closures, but I'm don't understand at this moment. Can anyone help me to learn how to solve this situation?

 $(document).ready(function() { var counter1 = 0; var counter2 = 0; // Our Cats catsArr = [{ name: "Michelangelo", picture: "img/cat-picture.jpg", counter: "counter1", clicks: 0, listenerClass: "cat-picture-1" }, { name: "Ivanka", picture: "img/cat-picture-2.jpg", counter: "counter2", clicks: 0, listenerClass: "cat-picture-2" } ]; // Our main function to print the cats function createDisplay(catsArr) { for (i = 0; i < catsArr.length; i++) { $('.cats-place').append(` <div class=" cat-img col s6 m6 l6 xl5 offset-xl1 center-align"> <p class="cat-1-name flow-text">${catsArr[i].name}</p> <img class="responsive-img ${catsArr[i].listenerClass}" src="${catsArr[i].picture}" alt="cat picture"> <div class="col s12 m6 offset-m3 center-align"> <p class="flow-text">Counter = <span class="${catsArr[i].counter}">0</span></p> </div> </div>`) $(`.${catsArr[i].listenerClass}`).click(function() { var counter = 0; counter = counter + 1; $(`.${catsArr[i].counter}`).html(counter); }) } }; // Executing the function createDisplay(catsArr) }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title>Cat Clicker</title> <link rel="stylesheet" href="css\\style.css"> <!-- Compiled and minified CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css"> <!-- Compiled and minified JavaScript --> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script> </head> <body> <div class="container"> <div class="row cats-place"> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E=" crossorigin="anonymous"></script> <script src="js\\app.js"></script> </body> </html> 

The issue is that you are trying to reference the i inside the click handler, which has already been iterated to be equal to the length of the array, so it is out of scope. You need to use a closure, or store this variable in another variable, so it is unchanged and preserved for your click handlers.

This modified version uses the forEach method to iterate over the array. An advantage of this is it uses a callback and passes in the element and the index, which for the scope of each call to the callback do not change.

 $(document).ready(function() { var counter1 = 0; var counter2 = 0; // Our Cats catsArr = [{ name: "Michelangelo", picture: "img/cat-picture.jpg", counter: "counter1", clicks: 0, listenerClass: "cat-picture-1" }, { name: "Ivanka", picture: "img/cat-picture-2.jpg", counter: "counter2", clicks: 0, listenerClass: "cat-picture-2" } ]; // Our main function to print the cats function createDisplay(catsArr) { catsArr.forEach(function(cat) { $('.cats-place').append(` <div class=" cat-img col s6 m6 l6 xl5 offset-xl1 center-align"> <p class="cat-1-name flow-text">${cat.name}</p> <img class="responsive-img ${cat.listenerClass}" src="${cat.picture}" alt="cat picture"> <div class="col s12 m6 offset-m3 center-align"> <p class="flow-text">Counter = <span class="${cat.counter}">0</span></p> </div> </div>`) var counter = 0; $(`.${cat.listenerClass}`).click(function() { $(`.${cat.counter}`).html(++counter); }) }); }; // Executing the function createDisplay(catsArr) }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title>Cat Clicker</title> <link rel="stylesheet" href="css\\style.css"> <!-- Compiled and minified CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css"> <!-- Compiled and minified JavaScript --> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script> </head> <body> <div class="container"> <div class="row cats-place"> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E=" crossorigin="anonymous"></script> <script src="js\\app.js"></script> </body> </html> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM