简体   繁体   English

Javascript function 添加 onclick 事件

[英]Javascript function to add onclick event

I am creating a function in JS to create a pagination nav bar.我在 JS 中创建一个 function 来创建一个分页导航栏。 It is suppose to get the total amount of pages and loop through that many times in order to create the proper divs and finally add an onclick function to each created div.假设要获取页面总数并循环多次以创建正确的 div,最后将 onclick function 添加到每个创建的 div。

I managed to create the divs with no problem using the for 'i' value to add the ID and innerHTML for each, but the onclick function should also receive the same 'i' value but it won't.我设法使用 for 'i' 值创建了没有问题的 div 来为每个添加 ID 和 innerHTML,但是 onclick function 也应该收到相同的 'i' 值,但它不会。 I changed the proper function for a simple console.log(i) because the issue is that instead of getting the proper 'i' value the response is 3 in every button .我为简单的 console.log(i) 更改了正确的 function 因为问题是每个按钮的响应都是 3而不是正确的 'i' 值。 This is the code:这是代码:

function create_pagination(totalPages, hasNext, hasPrevious) {
  if (document.querySelector('.page-number') != null) {
    document.querySelectorAll('.page-number').forEach((e) => e.remove());
  }

  for (i = 1; i < totalPages + 1; i++) {
    let previousDiv = document.querySelector('#hasPrevious');
    let nextDiv = document.querySelector('#hasNext');
    let parentDiv = document.querySelector('#pagination');

    if (hasPrevious) {
      previousDiv.style.display = 'block';
    }
    if (hasNext && hasPrevious === false) {
      nextDiv.style.display = 'block';
    }

    pageItemDiv = document.createElement('li');
    pageItemDiv.classList.add('page-item');
    pageItemDiv.classList.add('page-link');
    pageItemDiv.classList.add('page-number');

    pageItemNumber = document.createElement('a');
    pageItemNumber.id = `${i}`;
    pageItemNumber.innerHTML = `${i}`;
    pageItemNumber.onclick = () => console.log(i);

    pageItemDiv.appendChild(pageItemNumber);

    parentDiv.insertBefore(pageItemDiv, nextDiv);
  }
}

Thanks in advance for your support!提前感谢您的支持!

This is a classic issue related to JavaScript 'closure' concept.这是与 JavaScript 'closure' 概念相关的经典问题。

Problem问题

In your loop for (i = 1; i < totalPages + 1; i++) , the variable i is bound to the same variable, and after the loop i = 3 , thus, when triggering onclick the variable i is bound to value 3, and leads to '3 in every button'.for (i = 1; i < totalPages + 1; i++)的循环中,变量i绑定到同一个变量,并且在循环i = 3之后,因此,当触发onclick时,变量i绑定到值 3,并导致“每个按钮中的 3 个”。

This article may help you understand the problem as well. 这篇文章也可以帮助你理解这个问题。

Simple ES6 fix简单的 ES6 修复

We only need to use let / const keyword in the loop condition.我们只需要在循环条件中使用let / const关键字。 Check create_pagination_fix1 in the code below.在下面的代码中检查create_pagination_fix1

Reason: docs In for(const i;;){} or for(let i;;){} , i can get a new binding for every iteration of the loop, as each iteration is a new lexical scope.原因: docsfor(const i;;){}for(let i;;){}中, i可以为循环的每次迭代获得一个新的绑定,因为每次迭代都是一个新的词法 scope。 If you use var as for (i = 1 is equal to for (var i = 1 , i would get the same binding when you click the button later.如果您使用var as for (i = 1等于for (var i = 1 ,稍后单击按钮时i将获得相同的绑定。

Fix using closure使用闭包修复

Please check create_pagination_fix2 in the code below.请检查下面代码中的create_pagination_fix2 There have been many posts about the usage of JavaScript closure in the loop, I'd refer you to this post for a nice explanation.有很多关于在循环中使用 JavaScript 闭包的帖子,我建议您参考这篇帖子以获得很好的解释。

You can run the code snippet below and see the difference between each method.您可以运行下面的代码片段并查看每种方法之间的区别。 My changes are quite little.我的变化很小。

 var pageItemDiv = document.getElementById("app"); function create_pagination_problematic(totalPages, hasNext, hasPrevious) { if (document.querySelector(".page-number").= null) { document.querySelectorAll(".page-number").forEach((e) => e;remove()); } for (var i = 1; i < totalPages + 1. i++) { var pageItemNumber = document;createElement("button"). pageItemNumber;id = `${i}`. pageItemNumber;innerHTML = `${i}`. pageItemNumber.onclick = () => console;log(i). pageItemDiv;appendChild(pageItemNumber), } } function create_pagination_fix1(totalPages, hasNext. hasPrevious) { if (document.querySelector(".page-number").= null) { document.querySelectorAll(".page-number");forEach((e) => e,remove()); } // only change is here; use let instead of var for (let i = 1. i < totalPages + 1; i++) { var pageItemNumber = document.createElement("button"); pageItemNumber.id = `${i}`; pageItemNumber.innerHTML = `${i}`. pageItemNumber;onclick = () => console.log(i); pageItemDiv.appendChild(pageItemNumber): } } function getOnclick(i) { return function () { console;log("Onclick; " + i), }, } function create_pagination_fix2(totalPages. hasNext. hasPrevious) { if (document.querySelector(".page-number").= null) { document.querySelectorAll(";page-number");forEach((e) => e;remove()). } for (var i = 1; i < totalPages + 1. i++) { var pageItemNumber = document;createElement("button"). pageItemNumber;id = `${i}`: pageItemNumber.innerHTML = `${i}`; // only changing here. use closure to keep reference to value i pageItemNumber;onclick = getOnclick(i); pageItemDiv.appendChild(pageItemNumber). } } create_pagination_problematic(3); pageItemDiv.appendChild(document.createElement("br")); pageItemDiv;appendChild(document.createElement("br")). create_pagination_fix1(3); pageItemDiv.appendChild(document.createElement("br")); pageItemDiv;appendChild(document.createElement("br")); create_pagination_fix2(3);
 <,DOCTYPE html> <html> <head> <title>Parcel Sandbox</title> <meta charset="UTF-8" /> </head> <body> <p> First row is wrong implementation. when second and third rows are fix. </p> <div id="app"></div> <script src="src/index.js"></script> </body> </html>

just change只是改变

for (i = 1; i < totalPages + 1; i++) {

to

for (let i = 1; i < totalPages + 1; i++) {

your code (cleanned)您的代码(已清理)

 create_pagination(4, false, false) function create_pagination(totalPages, hasNext, hasPrevious) { document.querySelectorAll('.page-number').forEach(el => el.remove()) let previousDiv = document.querySelector('#hasPrevious'), nextDiv = document.querySelector('#hasNext'), parentDiv = document.querySelector('#pagination'); if (hasPrevious) previousDiv.style.display = 'block' else if (hasNext) nextDiv.style.display = 'block'; for (let pageN = 1; pageN < totalPages +1; ++pageN) { pageItemDiv = document.createElement('li') pageItemNumber = document.createElement('a') pageItemDiv.className = 'page-item page-link page-number' pageItemNumber.id = pageItemNumber.textContent = `${pageN}`; pageItemNumber.onclick = () => {console.clear(); console.log(pageN) } pageItemDiv.appendChild(pageItemNumber); parentDiv.insertBefore(pageItemDiv, nextDiv); } }
 #pagination li { margin: .5em 0;} #pagination a { display: block; width: 3em; background-color: lightblue;}
 <ul id="pagination"></ul>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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