简体   繁体   English

在 for 循环中添加 onClick 事件

[英]Adding onClick event in a for loop

I am a beginner in Javascript.我是 Javascript 的初学者。 What I am trying to do is when a user clicks on "Click to start loop", the first <li> will be 1. The second time the user clicks it, it will be 2, and the third time, it will be 3. After the third click, the loop will break.我想要做的是当用户点击“点击开始循环”时,第一个<li>将是 1。用户第二次点击它,它将是 2,第三次,它将是 3 . 第三次点击后,循环会中断。

The issue with my code is that it always displays the number 3 instead of starting from 1 and going all the way to 3.我的代码的问题是它总是显示数字 3,而不是从 1 开始一直到 3。

 function myFunction() { demo = document.getElementById("demo") ul = document.createElement("ul") demo.appendChild(ul) li = document.createElement("li") ul.appendChild(li) for (let i = 1; i <= 3; i++){ li.innerText = i } }
 <p id="demo" onclick="myFunction()">Click to start loop</p>

It is because, there is only one 'li' element created before loop starts and at the end of loop, it is just updating the final innterText.这是因为,在循环开始之前和循环结束时只创建了一个 'li' 元素,它只是在更新最终的内部文本。

You can fix it by moving li creation code to loop您可以通过将 li 创建代码移动到循环来修复它

function myFunction() {
demo = document.getElementById("demo") 
ul = document.createElement("ul")
demo.appendChild(ul)
                       <--- from here

for (let i = 1; i <= 3; i++){   
    li = document.createElement("li")  <--- to here
    ul.appendChild(li)     
    li.innerText = i     
}

} }

You just have to save the current loop value in some place:您只需将当前循环值保存在某个地方:

 let i = 1; function myFunction() { // Check for i value if (i === 4) return; demo = document.getElementById("demo") ul = document.createElement("ul") demo.appendChild(ul) li = document.createElement("li") ul.appendChild(li) // Update the i value li.innerText = i++; }
 <p id="demo" onclick="myFunction()">Click to start loop</p>

One solution could be to create a global variable with initial value set to 1 and increase it every time there is a click on your <p> tag.一种解决方案可能是创建一个初始值设置为 1 的全局变量,并在每次单击<p>标记时增加它。

I have implemented the same using the global variable counter .我已经使用全局变量counter实现了相同的功能。

 <p id="demo" onclick="myFunction()">Click to start loop</p> <script> var counter = 1; function myFunction() { if(counter === 4){ return; } demo = document.getElementById("demo"); ul = document.createElement("ul"); demo.appendChild(ul); li = document.createElement("li"); ul.appendChild(li); li.innerText = counter; counter++; } </script>

I think you should put li = document.createElement("li") inside of the loops我认为您应该将li = document.createElement("li")放入循环中

index.js index.js

function myFunction(status) {
    demo = document.getElementById("demo") 
    ul = document.createElement("ul")
    demo.appendChild(ul)
                
    for (let i=1; i<=3; i++) {
        li = document.createElement("li")     
        li.innerText = i     
        ul.appendChild(li) 
    }
}

This is unclear, are you looking for javascript function generator ?这个不清楚,你在找javascript function 发电机吗?

 const ul_List = document.body.appendChild( document.createElement('ul') ), generator = (function* () { for (let i = 0; (++i < 4);) { ul_List.appendChild( document.createElement('li') ).textContent = i yield } })()
 <p id="demo" onclick="generator.next()" >Click to 3 times loop</p>

Counters计数器

A function that deals with an incrementing variable (aka counter) usually declares or defines it as a number outside of a loop then iterates the variable with a ++ or += operator within the loop.处理递增变量(又名计数器)的 function 通常将其声明或定义为循环外的数字,然后在循环内使用+++=运算符迭代变量。 But would a loop within an event handler that increments a number by +1 per click make much sense?但是,事件处理程序中的循环是否使数字每次点击增加 +1 有意义? So forget about iterations based on a single run of a function/event handler.所以忘记基于函数/事件处理程序的单次运行的迭代。

The next problem is that once the function/event handler is done, the counter is garbage collected (deleted from memory), so on the next click it is back to what it was initially (usually 0) -- so you need the user to click a HTML element, increase a number by one, and increase it by one per click thereafter.下一个问题是,一旦函数/事件处理程序完成,计数器就会被垃圾收集(从内存中删除),所以在下一次点击时它会回到最初的状态(通常为 0)——所以你需要用户单击 HTML 元素,将数字加一,然后每次单击将其加一。 There a few ways to keep the counter's last value:有几种方法可以保持计数器的最后一个值:

HTML/DOM HTML/DOM

  • Store the last value in a HTML form control by [value]通过[value]将最后一个值存储在 HTML 表单控件中
    let counter = 0; counter++; document.forms[0].count.value = counter; .... <input id='count' type='hidden' value='0'><!--value will be '1'-->
  • Store the last value in any other type of HTML element by [data-*] or text content通过[data-*]或文本内容将最后一个值存储在任何其他类型的 HTML 元素中
    document.querySelector('.count').dataset.idx = counter; .... <nav class='count' data-idx='1'></nav> document.querySelector('aside').textContent = counter; .... <aside>2</aside>
  • Keep in mind any value stored in HTML is converted into a string so when getting the variable counter value you must convert it back into a real number:请记住,存储在 HTML 中的任何值都会转换为字符串,因此在获取变量counter值时,您必须将其转换回实数:
     parseInt(document.forms[0].count.value); parseFloat(document.querySelector('.count').dataset.idx); Number(document.querySelector('aside').textContent);

Closures闭包

A better way IMO is to deal with variable scope. IMO 更好的方法是处理变量 scope。 If you noticed in the previous code, let and const are used instead of var .如果您在前面的代码中注意到,使用letconst代替var The reason for this is scope.其原因是 scope。

Function Scope: If var was used, then all variables would be influenced by anything inside or the immediate outside of the function it is in. If completely outside of all functions then it is global (much more susceptible to side effects and buggy behavior). Function Scope:如果使用了var ,那么所有变量都将受到 function 内部或直接外部的任何东西的影响。

Block Scope: let and const scope is block which means they can only be accessed within the brackets they are located in:块 Scope: letconst scope 是块,这意味着它们只能在它们所在的括号内访问:

var G = `any function, method, expression, etc can affect it or be affected
         by it`;
function clickHandler(e) {
  var L = `vulnerable to anything within the function and immediately 
           outside the function`;
  if (e.target.matches('button')) {
    let A, 
    const B = `only affects or get affected only by things within the 
               brackets`;
    var C = `even buried deep within a function it will be hoisted to be 
             accessible to everything within this function`;
  }
  function addItem(node, count) {
    /* Although a function defined within another function it cannot access 
      A or B*/
  }
}

Wrapping a function/event handler in another function in order to provide an isolated scope and an environment wherein variables can exist past runtime and avoid garbage collection is a closure .将函数/事件处理程序包装在另一个 function 中以提供隔离的 scope 和变量可以在运行时之后存在并避免垃圾收集的环境是闭包 The following examples are closures #1 is simple and #2 is more refined (user can edit each list item directly).以下示例是闭包#1 很简单,#2 更精致(用户可以直接编辑每个列表项)。 Go here for details on scope and closures. Go在此处了解有关 scope 和关闭的详细信息。

Example 1示例 1

 function init() { const ul = document.querySelector('ul'); let i = 0; function clickHandler(e) { i++; addItem(this, i); } ul.onclick = clickHandler; }; function addItem(list, counter) { const li = document.createElement('li'); list.append(li); li.textContent = counter; }; init();
 <ul>Click to Add Item</ul>

Example 2示例 2

 function init() { const ui = document.forms[0]; let counter = 1; function addItem(event) { const clicked = event.target; if (clicked.matches('legend')) { const list = clicked.nextElementSibling; let marker = `${counter++}`.padStart(2, '0'); list.insertAdjacentHTML('beforeEnd', `<li contenteditable data-idx="${marker}"></li>`); } } ui.onclick = addItem; }; init();
 form { font: 1.5ch/1 Consolas; } legend { font-size: large; font-weight: bold; user-select: none; cursor: pointer; } legend::after { content: 'Click to Add Item'; font-size: small; } ul { list-style: none; } li { margin: 5px 11px 5px 9px; padding: 4px 8px; border-bottom: 1px solid #980; } li::marker { display: list-item; content: attr(data-idx)'.'; margin-bottom: -2px; }
 <form> <fieldset> <legend>List<br></legend> <ul></ul> </fieldset> </form>

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

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