Javascript为什么单击eventListener为前一个图像触发?

时间:2018-04-23 01:29:47

标签: javascript html

基本上,我正在尝试构建一个猫点击应用程序,我们点击猫图片来增加点击次数。我们可以使用下拉菜单更改正在显示的猫图片。问题是,当我更改图像并单击它时,前一个图像的计数也会增加。 JSBin link with code

var cats = {
  cat1: ['Tiger ', "https://lh3.ggpht.com/nlI91wYNCrjjNy5f-S3CmVehIBM4cprx-JFWOztLk7vFlhYuFR6YnxcT446AvxYg4Ab7M1Fy0twaOCWYcUk=s0#w=640&h=426", 0],
  cat2: ['Puss',
    "https://lh3.ggpht.com/kixazxoJ2ufl3ACj2I85Xsy-Rfog97BM75ZiLaX02KgeYramAEqlEHqPC3rKqdQj4C1VFnXXryadFs1J9A=s0#w=640&h=496", 0
  ],
  cat3: ['Smokey',
    "https://lh5.ggpht.com/LfjkdmOKkGLvCt-VuRlWGjAjXqTBrPjRsokTNKBtCh8IFPRetGaXIpTQGE2e7ZCUaG2azKNkz38KkbM_emA=s0#w=640&h=454", 0
  ],
  cat4: ['Misty',
    "https://images.unsplash.com/photo-1482066490729-6f26115b60dc?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=2e749e5a9492af91a0c4e366e0f58bb4&auto=format&fit=crop&w=700&q=60", 0
  ],
  cat5: ['Ashes',
    "https://images.unsplash.com/photo-1457410129867-5999af49daf7?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=db366be68b7ffcb315597fcf0c1b6a51&auto=format&fit=crop&w=700&q=60", 0
  ],
  cat6: ['Kitty',
    "https://images.unsplash.com/photo-1417028441456-f283323fe2d6?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=5b2d5f4ce317590a93f0ff7ccc1abd39&auto=format&fit=crop&w=700&q=60", 0
  ]

}

//the following code make sure we have one cat info available as we load the page.
render(cats);

//load cats from drop down.
function showCat() {
  var val = document.getElementById('mySelect').value;
  document.getElementById('catPic').src = '';
  render(cats, val);
}

function render(cats, val = 'cat1') {
  document.getElementById('catName').innerHTML = cats[val][0];

  document.getElementById('catPic').src = cats[val][1];

  var clickCount = cats[val][2];
  console.log("click1 : " + clickCount);
  document.getElementById('catCount').innerHTML = 'Click Count : ' + clickCount;

  var elemCat = document.getElementById('catPic');
  elemCat.addEventListener('click', function() {
    clickCount++;
    cats[val][2] = clickCount;
    console.log("click2 : " + clickCount);
    document.getElementById('catCount').innerHTML = "Click Count : " + clickCount;
  }, false);
  elemCat.removeEventListener('click', function() {
    console.log('Removing Event Listener');
  }, false);
}
<html>

<head>
  <title>Cat Clicker</title>
</head>

<body>
  <select id="mySelect" onchange="showCat()" name="Select the Cat">
    <option value="cat1">Tiger</option>
    <option value="cat2">Puss</option>
    <option value="cat3">Smokey</option>
    <option value="cat4">Misty</option>
    <option value="cat5">Ashes</option>
    <option value="cat6">Kitty</option>
  </select>
  <h1 id="catName"></h1>
  <img id="catPic" src="#" alt="cat-photo">
  <h3 id="catCount"></h3>
</body>

</html>

2 个答案:

答案 0 :(得分:2)

您需要对您调用addEventListener的函数进行静态引用,以便稍后将其删除。添加elemCat.addEventListener('click', function () {的侦听器永远不会被删除,因为它是匿名的,不存储在变量中。您应该将侦听器函数分配给外部变量,以便以后可以remove

var cats = {
  cat1: ['Tiger ', "https://lh3.ggpht.com/nlI91wYNCrjjNy5f-S3CmVehIBM4cprx-JFWOztLk7vFlhYuFR6YnxcT446AvxYg4Ab7M1Fy0twaOCWYcUk=s0#w=640&h=426", 0],
  cat2: ['Puss',
    "https://lh3.ggpht.com/kixazxoJ2ufl3ACj2I85Xsy-Rfog97BM75ZiLaX02KgeYramAEqlEHqPC3rKqdQj4C1VFnXXryadFs1J9A=s0#w=640&h=496", 0
  ],
  cat3: ['Smokey',
    "https://lh5.ggpht.com/LfjkdmOKkGLvCt-VuRlWGjAjXqTBrPjRsokTNKBtCh8IFPRetGaXIpTQGE2e7ZCUaG2azKNkz38KkbM_emA=s0#w=640&h=454", 0
  ],
  cat4: ['Misty',
    "https://images.unsplash.com/photo-1482066490729-6f26115b60dc?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=2e749e5a9492af91a0c4e366e0f58bb4&auto=format&fit=crop&w=700&q=60", 0
  ],
  cat5: ['Ashes',
    "https://images.unsplash.com/photo-1457410129867-5999af49daf7?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=db366be68b7ffcb315597fcf0c1b6a51&auto=format&fit=crop&w=700&q=60", 0
  ],
  cat6: ['Kitty',
    "https://images.unsplash.com/photo-1417028441456-f283323fe2d6?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=5b2d5f4ce317590a93f0ff7ccc1abd39&auto=format&fit=crop&w=700&q=60", 0
  ]

}

//the following code make sure we have one cat info available as we load the page.
render(cats);

//load cats from drop down.
function showCat() {
  var val = document.getElementById('mySelect').value;
  document.getElementById('catPic').src = '';
  render(cats, val);
}

var currentListener;
function render(cats, val = 'cat1') {
  document.getElementById('catName').innerHTML = cats[val][0];
  document.getElementById('catPic').src = cats[val][1];
  var clickCount = cats[val][2];
  console.log("click1 : " + clickCount);
  document.getElementById('catCount').innerHTML = 'Click Count : ' + clickCount;
  var elemCat = document.getElementById('catPic');
  if (currentListener) elemCat.removeEventListener('click', currentListener);
  currentListener = function() {
    clickCount++;
    cats[val][2] = clickCount;
    console.log("click2 : " + clickCount);
    document.getElementById('catCount').innerHTML = "Click Count : " + clickCount;
  }
  elemCat.addEventListener('click', currentListener);
}
<html>

<head>
  <title>Cat Clicker</title>
</head>

<body>
  <select id="mySelect" onchange="showCat()" name="Select the Cat">
    <option value="cat1">Tiger</option>
    <option value="cat2">Puss</option>
    <option value="cat3">Smokey</option>
    <option value="cat4">Misty</option>
    <option value="cat5">Ashes</option>
    <option value="cat6">Kitty</option>
  </select>
  <h1 id="catName"></h1>
  <img id="catPic" src="#" alt="cat-photo">
  <h3 id="catCount"></h3>
</body>

</html>

答案 1 :(得分:1)

问题

发生的事情是你每次重复使用相同的elemCat(你只需设置innerHTML),但是在你的render()上,你总是设置一个新的事件监听器。在渲染功能的最底部,你有

elemCat.removeEventListener('click', function () {
        console.log('Removing Event Listener');
    }, false);

我认为你的意思是删除旧的听众,但这不是它的工作方式。 removeEventListener所做的是删除click处理程序当且仅当传入的函数与传递给addEventListener的函数相同时。这是不可能的,因为您在addEventListener电话中使用匿名功能。您永远不会保存对该功能的引用,因此您以后无法将其删除。

修复

解决此问题的最佳方法是仅拨打addEventListener一次。这样您就不必担心管理点击处理程序。如果您只有一个事件处理程序,那么它将如何知道要递增的计数?这就是数据道具的来源。您可以将猫名称保存为data-cat-name,然后在每次点击时将其读取:

onClick代码

请注意,唯一的区别是将catName拉出元素,然后根据它增加计数

const elemCat = document.getElementById('catPic');
elemCat.addEventListener('click', function() {
  const catName = elemCat.dataset.catName;
  cats[catName][1] += 1; // increment the count
  document.getElementById('catCount').innerHTML = 'Click Count : ' + cats[catName][1];
});

onChange代码

您的onChange代码看起来大致相同。

const val = document.getElementById('mySelect').value;
const catPic = document.getElementById('catPic');
catPic.src = cats[val][0];
catPic.dataset.catName = val;
相关问题