【问题标题】:DOM manipulation inside loop happens too fast循环内的 DOM 操作发生得太快
【发布时间】:2019-11-11 07:12:45
【问题描述】:

尝试以不同的颜色闪烁 div,它们之间有一段时间(不使用 jquery)。该程序在调试器中运行良好,但在运行时,所有更改都发生得太快,用户看不到任何东西。

尝试使用 setTimeout 无济于事(可能没有正确使用)

function makeBoard() {
var squareNum = 4
var selected
container = document.createElement('div')
container.id = 'container'
document.body.appendChild(container);
for (let index = 0; index < squareNum; index++) {
    squareDiv = document.createElement('div')
    squareDiv.className = 'square'
    squareDiv.id = '' + (index + 1)
    container.appendChild(squareDiv)
}
selected = document.getElementById('1')
selected.classList.add('selected')
return selected
}

function dimSwitch() {
var turnCnt = 1
var posIndex = 0
var selectedDivs = []
var tempCnt = 0
var tempIndex = 0
var timeNum = getMaxPos()
while (tempCnt < timeNum) {
    var posIndex = posArr.indexOf(turnCnt, tempIndex)
    tempIndex = posIndex + 1
    while (posIndex !== -1) {
        selectedDivs.push(document.getElementById(posIndex + 1 + ''))
        posIndex = posArr.indexOf(turnCnt, tempIndex)
        tempIndex = posIndex + 1
    } 
    selectDiv(selectedDivs) //After this i would like a small delay
    turnCnt++
    tempCnt++
    for (let index = 0; index < selectedDivs.length; index++) {
        selectedDivs[index].classList.remove('selected')
    }
    selectedDivs = []
}
}

function drawMove(currDiv, direction) {
 var nextDiv
 currDiv.classList.remove('selected')
 nextDiv = document.getElementById((parseInt(currDiv.id) + direction))
 nextDiv.classList.add('selected')
 return nextDiv
}

function selectDiv(divs) {
for (let index = 0; index < divs.length; index++) {
    divs[index].classList.add('selected')
}
}
function getMaxPos() {
var maxNum = 0
for (let index = 0; index < posArr.length; index++) {
    if (posArr[index] > maxNum) maxNum = posArr[index]
}
return maxNum
}

var TurnNum = 4 //Number of turns
var posArr = [1]
var turnCnt = 1
var currDiv = makeBoard()

document.onkeydown = function (event) {
switch (event.keyCode) {
    case 37:
        //Left Key -1
        posArr[turnCnt] = posArr[turnCnt - 1] - 1
        currDiv = drawMove(currDiv, -1)
        turnCnt++
        break;

    case 39:
        //Right key +1
        posArr[turnCnt] = posArr[turnCnt - 1] + 1
        currDiv = drawMove(currDiv, 1)
        turnCnt++
        break;

    case 40:
        currDiv.classList.remove('selected')
        dimSwitch()
        break;
}
if (turnCnt === TurnNum) {
    currDiv.classList.remove('selected')
    dimSwitch()
}
};

函数 selectDivs 应该在每次执行之间运行一段时间 每当使用延迟或超时时,它都会冻结或正常工作 在我删除 for 循环中的类之前,用户应该能够看到哪些 div 为红色(“选定”类)。

JS FIDDLE FULL CODE

这就是我尝试使用 setTimeout 的方式,但其余代码一直在后台运行,而我看到的所有 div 都是红色的:

setTimeout(function(){ 
for (let index = 0; index < selectedDivs.length; index++) { 
       selectedDivs[index].classList.remove('selected') 
   } 
 },1000) 

【问题讨论】:

  • 显然这段代码会立即运行。你是怎么用 setTimeout 没用的?
  • setTimeout(function(){ for (let index = 0; index
  • 请发布一个最小的工作示例(或者在这种情况下不工作),包括HTML(和任何重要的东西),所以人们不要重建你的案子并不难。这样就可以更轻松、更快捷地提出解决方案。

标签: javascript html settimeout delay


【解决方案1】:

您已将循环代码放在 setTimeout 块中,因此整个循环将在 1000 毫秒后运行,一目了然。如果您希望元素一个一个地出现 1 秒延迟,您可以将逻辑更改为这样,为每个元素设置不同的超时 (1000 * index)

for (let index = 0; index < selectedDivs.length; index++) { 
   setTimeout(function(){ 
        selectedDivs[index].classList.remove('selected') 
    }
    , (1000 * index)
    )
} 

【讨论】:

  • 这个循环应该一目了然。我希望在我运行 selectDivs 函数后发生延迟,以便用户可以看到哪些 div 是红色的
  • 我在第二个 while 循环(让 div 被改变并改变它们的循环)和你展示的 for 循环上实现了这个逻辑,它工作得很好!非常感谢。
【解决方案2】:

简单的方法是进行递归循环,使用超时来延迟对自身的调用。下面的概念证明:

var childDivs = document.querySelectorAll('.child'); 

function selectDivs(divs, index, delay) {
  divs[index].classList.add('selected');
  
  delay = delay || 1000;  // if you want to change the delay
  index++
  
  if (index < divs.length) {
    setTimeout(function() {
      selectDivs(divs, index, delay);    
    }, delay);    
  }
}
.flex-container {
  display: flex;
  flex-wrap: wrap;
}

.child {
  height: 100px;
  width: 100px;
  box-sizing: border-box;

  background-color: yellow;
  border: 1px solid #000;
}

.selected {
  background-color: red;
}
<body onload="selectDivs(childDivs, 0)">

  <div class="flex-container">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
  </div>
  
</body>

我会尽可能亲自使用 CSS,设置一个 CSS 变量来延迟更改。只是为了能够更容易地了解 DOM 中发生的事情。

var childDivs = document.querySelectorAll('.child'); 

function selectDivs(children) {
  let child = {};

  for (let i = 0; i < children.length; i++) {
    child = children[i];
    
    child.style.setProperty('--background-animation-delay', i+'s');
    child.classList.add('selected');  
  }
}
.flex-container {
  display: flex;
  flex-wrap: wrap;
}

.child {
  --background-animation-delay: 0s;
  
  height: 100px;
  width: 100px;
  box-sizing: border-box;

  background-color: #ffff00;
  border: 1px solid #000;
  
  transition: background-color 0s var(--background-animation-delay);
}

.selected {
  background-color: #ff0000;
}
<body onload="selectDivs(childDivs)">

  <div class="flex-container">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
  </div>
  
</body>

【讨论】:

    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多