简体   繁体   English

如何为具有相同名称的 div 显示相同的功能?

[英]How do I display the same function for the divs with the same name?

I built a script that has a data-target.我构建了一个具有数据目标的脚本。 When I load the page it will make a transition with 1ms from 0 to the data-target I selected.当我加载页面时,它将从 0 到我选择的数据目标进行 1ms 的转换。 Now, for the first one works just fine, but I have 2 other divs with the same class, and I want them to do the same thing, the last 2 have different data-targets, of course.现在,对于第一个工作得很好,但是我有 2 个其他 div 具有相同的类,我希望它们做同样的事情,当然,最后 2 个有不同的数据目标。

I tried querySelectorAll, never worked, maybe forEach?我试过 querySelectorAll,从来没有用过,也许是 forEach? But I don't fully understand how to use it.但我并不完全了解如何使用它。 Can anybody help me fix this problem?有人可以帮我解决这个问题吗?

 let divContainer = document.querySelector('.test'); let dataTarget = divContainer.getAttribute('data-target'); let divValue = 0; function increaseAnimation() { if (divValue <= dataTarget) { divContainer.innerHTML = divValue; divValue = divValue + 1; setTimeout(increaseAnimation, 1); } } increaseAnimation();
 <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="500"></div> <p>End</p> <div class="test" data-target="500"></div>

querySelectorAll is likely to feature in the solution, yes. querySelectorAll可能会在解决方案中出现,是的。 For instance, if you want all of the counters to run at the same time, you find all the .test elements and do the same thing with all of them:例如,如果您希望所有计数器同时运行,您可以找到所有.test元素并对它们执行相同的操作:

 document.querySelectorAll('.test').forEach(divContainer => { // There will be separate copies for each of these for each `.test` element let dataTarget = divContainer.getAttribute('data-target'); let divValue = 0; function increaseAnimation() { if (divValue <= dataTarget) { divContainer.innerHTML = divValue; divValue = divValue + 1; setTimeout(increaseAnimation, 1); } } increaseAnimation(); });
 <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="500"></div> <p>End</p> <div class="test" data-target="500"></div>

If you want to do them one after another, you'd probably store the list and remember the index of the current one, then move on to the next when done with it:如果您想一个接一个地执行它们,您可能会存储列表并记住当前列表的索引,然后在完成后继续下一个:

 const divContainers = document.querySelectorAll('.test'); let index = 0; processCurrentContainer(); function processCurrentContainer() { const divContainer = divContainers[index]; if (!divContainer) { return; } let dataTarget = divContainer.getAttribute('data-target'); let divValue = 0; function increaseAnimation() { if (divValue <= dataTarget) { divContainer.innerHTML = divValue; divValue = divValue + 1; setTimeout(increaseAnimation, 1); } else { // Done with this one, do the next if any ++index; processCurrentContainer(); } } increaseAnimation(); }
 <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="500"></div> <p>End</p> <div class="test" data-target="500"></div>


Side note:边注:

Depending on how you want this animation to behave, you might want to use requestAnimationFrame rather than setTimeout .根据您希望此动画的行为方式,您可能希望使用requestAnimationFrame而不是setTimeout With your current code, although the code requests a callback after 1ms, it will frequently be longer than that, potentially much longer, and the updates you're making aren't synchronized with the browser's painting of the page, which it will do 60 times/second at most (roughly 16.67ms between frames).使用您当前的代码,虽然代码在 1 毫秒后请求回调,但它通常会比这更长,可能更长,并且您所做的更新与浏览器的页面绘制不同步,它将执行 60次/秒最多(帧之间大约 16.67 毫秒)。 That means that if you want the animation to last exactly X milliseconds from beginning to end, the current code won't do that;这意味着如果您希望动画从开始到结束持续精确 X 毫秒,则当前代码不会这样做; it'll last longer than X milliseconds.它会持续超过 X 毫秒。 Here's the one-after-another example above measuring how long each segment took:这是上面一个接一个的示例,用于测量每个段花费的时间:

 const divContainers = document.querySelectorAll('.test'); let index = 0; processCurrentContainer(); function processCurrentContainer() { const start = Date.now(); const divContainer = divContainers[index]; if (!divContainer) { return; } let dataTarget = divContainer.getAttribute('data-target'); let divValue = 0; function increaseAnimation() { if (divValue <= dataTarget) { divContainer.innerHTML = divValue; divValue = divValue + 1; setTimeout(increaseAnimation, 1); } else { // Done with this one, do the next if any console.log(`Done, dataTarget = ${dataTarget}, elapsed = ${Date.now() - start}ms`); ++index; processCurrentContainer(); } } increaseAnimation(); }
 <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="500"></div> <p>End</p> <div class="test" data-target="500"></div>

To make it last X milliseconds more accurately (though not perfectly), and to avoid doing repeated calls to increaseAnimation when the browser hasn't done any painting in-between, use requestAnimationFrame to request a callback just before the browser paints the page, then figure how how many milliseconds have passed since the last time you updated, and update your animation appropriately for that number of milliseconds.为了让它更准确地持续 X 毫秒(虽然不是完美的),并避免在浏览器中间没有进行任何绘制时重复调用increaseAnimation动画,请在浏览器绘制页面之前使用requestAnimationFrame请求回调,然后计算自上次更新以来经过了多少毫秒,并在该毫秒数内适当地更新动画。 For instance, here's the one-after-another animation done that way:例如,这是以这种方式完成的一个接一个的动画:

 const divContainers = document.querySelectorAll('.test'); let index = 0; processCurrentContainer(); function processCurrentContainer() { const start = Date.now(); const divContainer = divContainers[index]; if (!divContainer) { return; } let dataTarget = divContainer.getAttribute('data-target'); let divValue = 0; let lastPainted = Date.now(); requestAnimationFrame(increaseAnimation); function increaseAnimation() { if (divValue <= dataTarget) { divContainer.innerHTML = divValue; const now = Date.now(); const elapsed = Date.now() - lastPainted; lastPainted = now; divValue += elapsed; // Since the value is meant to increase by milliseconds requestAnimationFrame(increaseAnimation); } else { // Done with this one, do the next if any console.log(`Done, dataTarget = ${dataTarget}, elapsed = ${Date.now() - start}ms`); ++index; processCurrentContainer(); } } }
 <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="500"></div> <p>End</p> <div class="test" data-target="500"></div>

Instead of document.queryselector() you should use document.getElementsByClassName() .取而代之的document.queryselector()你应该使用document.getElementsByClassName() Please check this code :请检查此代码:

 let divContainer = document.getElementsByClassName('test'); console.log(divContainer); for (let k of divContainer) { let dataTarget = k.getAttribute('data-target'); console.log(dataTarget); let divValue = 0; function increaseAnimation() { if (divValue <= dataTarget) { k.innerHTML = divValue; divValue = divValue + 1; setTimeout(increaseAnimation, 1); } } increaseAnimation(); }
 <body> <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="500"></div> <p>End</p> <div class="test" data-target="500"></div> </body>

  1. Use querySelectorAll to get an Array of elements.使用 querySelectorAll 获取元素数组。
  2. Loop through each element.循环遍历每个元素。
  3. Get the data-target attribute and the textContent of the element.获取textContentdata-target属性和textContent So if you wrap the number in a span or <b> , you still only get the number, and not the full code.因此,如果您将数字包装在 span 或<b> ,您仍然只能获得数字,而不是完整的代码。
  4. Place the container in the loop in a new array, if the condition haven't been met.如果未满足条件,则将容器放入循环中的新数组中。
  5. Replace divContainer with the new array.用新数组替换divContainer

I would rather go with requestAnimationFrame rather than setTimeout, to avoid unnecessary calculations.我宁愿使用requestAnimationFrame而不是 setTimeout,以避免不必要的计算。

It doesn't matter if you go with 0ms och 1ms in the setTimeout loop.在 setTimeout 循环中使用 0ms och 1ms 并不重要。 setTimeout and setInterval means that it won't trigger until that amount of time have passed, meaning that more time could pass before the method is executed. setTimeout 和 setInterval 意味着它不会触发,直到该时间段过去,这意味着在执行方法之前可能需要更多时间。

 var divContainer = document.querySelectorAll('.test'); // 1 function increaseAnimation() { let newIndex = 0; let newDivContainerArr = []; divContainer.forEach((container) => { // 2 let dataTarget = container.getAttribute('data-target'); // 3 let divValue = Number(container.textContent); container.textContent = ++divValue; if (divValue != dataTarget) { // 4 newDivContainerArr[newIndex++] = container; } }); divContainer = newDivContainerArr; // 5 if (divContainer.length) { setTimeout(increaseAnimation, 0); } } increaseAnimation();
 <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="500"></div> <p>End</p> <div class="test" data-target="500"></div>

I prefer simplicity, efficiency and readability:我更喜欢简单、高效和可读性:

 function increaseAnimation(el) { const dataTarget = el.dataset.target; let value = 0; function iteration(){ if (value < dataTarget) { el.innerHTML = value+=1; requestAnimationFrame(iteration); } } requestAnimationFrame(iteration) } document.querySelectorAll('.test').forEach( el => { increaseAnimation(el); })
 <p>Start</p> <div class="test" data-target="300"></div> <p>Middle</p> <div class="test" data-target="400"></div> <p>End</p> <div class="test" data-target="500"></div>

By the way if prefer faster animation you can increase the incrementation value like this:顺便说一下,如果更喜欢更快的动画,您可以像这样增加增量值:

el.innerHTML = value+=2; //3 , 4, ...

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

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