javascript - 具有动态生成内容的闭包

标签 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>

最佳答案

问题是您正在尝试引用点击处理程序内的 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>

关于javascript - 具有动态生成内容的闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50258486/

相关文章:

javascript - Webkit[Chrome/Safari] javascript 选择焦点错误的解决方法(在字段之间使用制表符时)

jQuery.attr() 保证小写?

jquery - .off 不解除绑定(bind) animationend 事件

jquery - 开始下载图像的事件是什么?

java - 处理导出的可执行引用

javascript - "function incrementNumber()"括起来的括号是可选的吗?

javascript - 如何禁用在 iframe 元素内拖动?

javascript - 在本地主机上刷新页面时,为什么文件下载会挂起,直到我关闭页面?

Javascript 保持模态隐藏

javascript - 使用 slickjs 手动滑动