具有动态生成内容的闭包

时间:2018-05-09 16:55:14

标签: javascript jquery

我正在尝试为动态创建的每个元素生成一个事件侦听器。问题出在createDisplay函数中。我经常收到一些错误。我读到解决方案是关闭的,但我现在还不明白。任何人都可以帮助我学习如何解决这种情况吗?

$(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>

1 个答案:

答案 0 :(得分:1)

问题在于您尝试引用单击处理程序中的i,该处理程序已经迭代为等于数组的长度,因此它超出了范围。您需要使用闭包,或将此变量存储在另一个变量中,因此它对于您的点击处理程序保持不变并保留。

此修改版本使用forEach方法迭代数组。这样做的一个优点是它使用一个回调并传入元素和索引,这对于每次调用回调的范围都不会改变。

$(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>