我有100个数字的数组,我想向其中20个数字添加活动类,该部分可以正常工作。但是我想在每个数字之间延迟。
我尝试使用settimeout,但是一次只能将所有数字延迟5秒,但是我想将活动类一一设置为5秒。请帮助。
function numbers() {
var activequantities;
activequantities = "@Html.DisplayFor(modelItem => item.Numbers)".split(",");
// this is array with sorted random numbers 20 of 100 example [22,33,46,57,etc]
function setClassNextItem(index)
{
if (index >= activequantities.lenght) return;
var value = activequantities[index];
$(`.grid-container div[data-tabid=${value}]`).addClass('active');
setTimeout(setClassNextItem(++index), 5000);
}
$(".grid-container div").removeClass('active');
setTimeout(setClassNextItem(0), 5000);
}
<div class="grid-container">
<div class="grid-item">
<div class="grid-container2">
<div class="grid-item2" data-tabid="1">1</div>
<div class="grid-item2" data-tabid="2">2</div>
<div class="grid-item2" data-tabid="3">3</div>
<div class="grid-item2" data-tabid="4">4</div>
</div>
一一添加活动班级。每个数字之间有5秒的延迟。
遍历过滤的元素数组并为回调添加(index + 1) * interval
超时以添加类名。
for (i = 0; i < 20; i++) {
setTimeout(
function (i) {
//$this.addClass("active");
console.log(`Add "active" class to element ${i}`);
},
(i + 1) * 1000, // shortened to 1 second for demo
i
);
}
尝试将activequantities
转换为数字数组并执行以下操作:
function setClassNextItem(index)
{
if (index >= activequantities.lenght) return;
var value = activequantities[index];
$(`.grid-container div[data-tabid=${value}]`).addClass('active');
setTimeout(setClassNextItem(++index), 5000);
}
$(".grid-container div").removeClass('active');
setTimeout(setClassNextItem(0), 5000);
欢迎使用stackoverflow!函数setTimeout
返回一个异步承诺,它将在x ms内解决。如果您循环运行此函数,则只需添加更多需要解决的承诺,但它们都将在接近同一时间解决。例如:
首先发送承诺:它将等待5秒钟一毫秒后,发送另一个等待5秒的承诺...5秒后,第一个Promise正确解析。1毫秒后,第二个承诺正确解析...
此行为使您的所有诺言几乎都在同一时间完成,仅在初始化诺言之后5秒钟。
在您的情况下,由于要以精确的间隔执行功能,因此需要setInterval
。 setInterval
功能在MS和一个功能中也要花费一些时间,但它每x ms重复一次此功能,或者直到间隔以编程方式停止为止。例如:
var counting = 0;
var myInterval = setInterval(function() {
//we do something...
console.log('loop:' + counting ++);
if(counting === 10) {
// we do this 10 times, than we stop the interval
clearInterval(myInterval);
}
}, 1000);
这里我使用1秒间隔,因为5个演示太长了。
Drew's answer是迄今为止最好和最简单的方法。另一种选择是走async function
/ promise
路线。
/**
* Time in milliseconds to wait between setting elements to active.
*/
const delayTime = 500, // shortened to half a second for the example
$app = $('#app');
/**
* Whether or not the routine is currently running.
*/
let stopped = true;
/**
* Returns a promise that resolves after the specified number of milliseconds.
*/
function delay(ms) {
return new Promise(res => setTimeout(res, ms));
}
function setActiveInSerial() {
// a little user-friendly UI work
stopped = !stopped;
if (stopped) {
$('#btn').text('Run');
} else {
$('#btn').text('Stop');
}
// promise that lets us serialize asynchronous functions
let promise = Promise.resolve();
$app.children().each(function() {
promise = promise.then(async() => {
if (stopped) {
return;
}
$(this).addClass('active');
// wait for `delayTime` to pass before resolving the promise
await delay(delayTime);
$(this).removeClass('active');
})
});
// mark the routine as stopped and reset the button
promise.then(() => {
stopped = true;
$('#btn').text('Run');
});
}
// populate with items
for (let i = 1; i <= 20; i++) {
$app.append($('<span>').text(`Item ${i}`));
}
// attach function to run button
$('#btn').click(setActiveInSerial);
#app {
display: flex;
flex-direction: column;
}
#app .active {
background-color: cyan;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn">Run</button>
<div id="app"></div>
该代码显然更长,但更灵活,对于学习promise和异步函数是一个很好的实践。它的另一个好处是,无需搜索元素的所有子元素即可删除active
类。