多个Elments的SetInterval(Vanilla JavaScript)
我已经使用Vanilla JavaScript创建了一个时间跟踪器;但是,当您有多个活动时,开始按钮功能无法正常工作。如果您有一个以上的活动DIV,则计时器与最后一个DIV同时启动,而第一个Divs Play按钮开始了最后一个Div。您能否查看我的newplay EventListener来确定我的方法是不正确的吗? (我是否错过了绑定,此,事件或E?
JavaScript:
let date = new Date().toLocaleDateString('en-us', { weekday:"long", year:"numeric", month:"short", day:"numeric"});
let showDate = document.getElementById("insert-date");
showDate.innerText=date;
//Get number of activity buttons for loop to add event listener to each
const btnLength = document.querySelectorAll(".opt-btn").length;
//Will append new div's here
const mainDiv = document.getElementById("activities");
//Add event listeners to each activity button & captures the buttonValue(activity name)
for (let i = 0; i < btnLength; i++){
document.querySelectorAll(".opt-btn")[i].addEventListener("click", function() {
const buttonValue = this.value;
addActivity(buttonValue);
});
//Onclick event creates the div, i, p , play, stop, timer text and appends to the main div
function addActivity(buttonValue){
const newDiv = document.createElement('div');
newDiv.classList.add("activity");
const newP = document.createElement('p');
newP.innerText = buttonValue;
newP.classList.add("act-p");
newDiv.appendChild(newP);
const newPlay =document.createElement('i');
newPlay.classList.add("fa-solid");
newPlay.classList.add("fa-play");
let activityInterval;
newPlay.addEventListener('click', () => {
activityInterval = setInterval(() => {
elapsedSeconds++
updateTimerValue()
}, 1000)
})
newDiv.appendChild(newPlay);
const newStop =document.createElement('i');
newStop.classList.add("fa-solid");
newStop.classList.add("fa-circle-stop");
newStop.addEventListener("click", clearInterval(activityInterval));
newDiv.appendChild(newStop);
newElapsedTime = document.createElement('p');
newElapsedTime.classList.add("elapsedTime-Text");
newElapsedTime.innerText = "00:00:00";
newDiv.appendChild(newElapsedTime);
mainDiv.appendChild(newDiv);
let elapsedSeconds = 0;
updateTimerValue()
function updateTimerValue() {
// Count the seconds, minutes and hours, convert to strings and pad the strings with leading 0's
const seconds = String(elapsedSeconds % 60).padStart(2, '0')
const minutes = String(parseInt(elapsedSeconds / 60 % 60)).padStart(2, '0')
const hours = String(parseInt(elapsedSeconds / 60 / 60)).padStart(2, '0')
// Use string interpolation for formatting the timer string
newElapsedTime.innerText = `${hours}:${minutes}:${seconds}`
}
}
}
html:
<section class="option-sec">
<div class = "container">
<div class = "row">
<div class ="col col-md-2">
<button class = "opt-btn" value="BATHROOM"><img src ="/images/bathroom.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="COMMUTE"><img src ="/images/commute.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="WORK"><img src ="/images/desk.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="ENT"><img src ="/images/ent.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="FAMILY"><img src ="/images/family.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="FITNESS"><img src ="/images/gym.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="MEAL"><img src ="/images/meal.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="MEDITATE"><img src ="/images/meditate.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="RELIGION"><img src ="/images/pray.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="SHOPPING"><img src ="/images/shopping.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="SLEEP"><img src ="/images/sleep.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="STUDY"><img src ="/images/study.png" class="option"></button>
</div>
</div>
</div>
</section>
<!--End Of Option Buttons-->
<section class="date-area">
<h1 class="date-hdr">CURRENT DATE: </h1>
<h2 class="date-hdr" id="insert-date"></h2>
</section>
<div class ="activity-container">
<div id="activities" class="activity-list"></div>
</div>
I have created a time tracker with vanilla Javascript; however, the start button functionality is not working correctly when you have more than one activity. If you have more than one activity div, the timer starts at the same time as the last div and the first divs play button starts the last div. Can you please look at my newPlay eventListener to determine how my approach was incorrect? (Am I missing a bind, this, event, or e?
JAVASCRIPT:
let date = new Date().toLocaleDateString('en-us', { weekday:"long", year:"numeric", month:"short", day:"numeric"});
let showDate = document.getElementById("insert-date");
showDate.innerText=date;
//Get number of activity buttons for loop to add event listener to each
const btnLength = document.querySelectorAll(".opt-btn").length;
//Will append new div's here
const mainDiv = document.getElementById("activities");
//Add event listeners to each activity button & captures the buttonValue(activity name)
for (let i = 0; i < btnLength; i++){
document.querySelectorAll(".opt-btn")[i].addEventListener("click", function() {
const buttonValue = this.value;
addActivity(buttonValue);
});
//Onclick event creates the div, i, p , play, stop, timer text and appends to the main div
function addActivity(buttonValue){
const newDiv = document.createElement('div');
newDiv.classList.add("activity");
const newP = document.createElement('p');
newP.innerText = buttonValue;
newP.classList.add("act-p");
newDiv.appendChild(newP);
const newPlay =document.createElement('i');
newPlay.classList.add("fa-solid");
newPlay.classList.add("fa-play");
let activityInterval;
newPlay.addEventListener('click', () => {
activityInterval = setInterval(() => {
elapsedSeconds++
updateTimerValue()
}, 1000)
})
newDiv.appendChild(newPlay);
const newStop =document.createElement('i');
newStop.classList.add("fa-solid");
newStop.classList.add("fa-circle-stop");
newStop.addEventListener("click", clearInterval(activityInterval));
newDiv.appendChild(newStop);
newElapsedTime = document.createElement('p');
newElapsedTime.classList.add("elapsedTime-Text");
newElapsedTime.innerText = "00:00:00";
newDiv.appendChild(newElapsedTime);
mainDiv.appendChild(newDiv);
let elapsedSeconds = 0;
updateTimerValue()
function updateTimerValue() {
// Count the seconds, minutes and hours, convert to strings and pad the strings with leading 0's
const seconds = String(elapsedSeconds % 60).padStart(2, '0')
const minutes = String(parseInt(elapsedSeconds / 60 % 60)).padStart(2, '0')
const hours = String(parseInt(elapsedSeconds / 60 / 60)).padStart(2, '0')
// Use string interpolation for formatting the timer string
newElapsedTime.innerText = `${hours}:${minutes}:${seconds}`
}
}
}
HTML:
<section class="option-sec">
<div class = "container">
<div class = "row">
<div class ="col col-md-2">
<button class = "opt-btn" value="BATHROOM"><img src ="/images/bathroom.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="COMMUTE"><img src ="/images/commute.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="WORK"><img src ="/images/desk.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="ENT"><img src ="/images/ent.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="FAMILY"><img src ="/images/family.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="FITNESS"><img src ="/images/gym.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="MEAL"><img src ="/images/meal.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="MEDITATE"><img src ="/images/meditate.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="RELIGION"><img src ="/images/pray.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="SHOPPING"><img src ="/images/shopping.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="SLEEP"><img src ="/images/sleep.png" class="option"></button>
</div>
<div class ="col col-md-2">
<button class = "opt-btn" value="STUDY"><img src ="/images/study.png" class="option"></button>
</div>
</div>
</div>
</section>
<!--End Of Option Buttons-->
<section class="date-area">
<h1 class="date-hdr">CURRENT DATE: </h1>
<h2 class="date-hdr" id="insert-date"></h2>
</section>
<div class ="activity-container">
<div id="activities" class="activity-list"></div>
</div>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
tldr;
使用前声明变量。
在严格模式本来会产生一个本来会产生一个,将脚本写入使用
newelapsedtime
在使用之前尚未声明的时间错误。
在 sloppy模式>没有声明会导致任何活动的“播放”点击处理程序创建或覆盖共享的全局对象属性
window.newelapsedtime
而不会生成错误。在处理程序的执行上下文中声明变量,该变量将活动添加到
Maindiv
似乎可以求解彼此干扰的活动点击。解决方案的示例不会实现停止(或暂停和恢复),如果play
&lt; i&gt;
元素多次单击相同的活动:我完全建议以严格的模式编写代码,并因此解决编译器所产生的任何错误。
TLDR;
Declare variables before use.
Writing the script in strict mode would have generate a compile time error that
newElapsedTime
has not been declared before use.In sloppy mode however, assignment to
newElapsedTime
without declaration causes any activity's "play" click handler to create or overwrite the value of a shared global object propertywindow.newElapsedTime
with no error generated.Declaring the variable in the execution context of the handler which added the activity to
mainDiv
seems to solve activity clicks interfering with each other.This example of a solution does not implement stop (or pause and resume) and logs an error if the play
<i>
element is clicked multiple times for the same activity:I thoroughly recommend writing code in strict mode and resolving any errors generated by the compiler because of it.
问题可能是在此行中:
每次您调用
addactivity()
,您最终会重新定义activity Interval
to to The Interval to The Interval to The Interval Tem the Instrain创建的活动。因此,在stoptimer()
中,您只需停止最新计时器。相反,
Activity Interval
需要是本地变量。首先在事件处理程序之外进行delcare,然后在stoptimer()
中编写箭头函数回调:local声明:
callback: callback:
这也是一个codesandbox: https://codesandbox.io/s/zealy-jepealy-jepsen-7gc4fn?gc4fn?file=/src/index/index.file=/src/index。 JS:1100-1286
(我没有图像,“日期”只是一个占位符)
The issue likely is with this line:
Each time you call
addActivity()
, you end up redefiningactivityInterval
to the interval specific to the most recent activity created. Therefore, instopTimer()
, you only stop the most recent timer.Instead,
activityInterval
needs to be a local variable. Delcare it outside the event handler first, and write a arrow function callback instopTimer()
:local declaration:
callback:
Here's a codesandbox too: https://codesandbox.io/s/zealous-jepsen-7gc4fn?file=/src/index.js:1100-1286
(I didn't have the images, and "date" is just a placeholder)