【问题标题】:How to update DOM in each loop iteration?如何在每次循环迭代中更新 DOM?
【发布时间】:2018-01-05 15:20:30
【问题描述】:

我有以下课程:

// Population class
class Population {

    constructor(size, target, mutationRate, minFitness) {
        this.target = target;
        this.size = size;
        this.individuals = [];
        // contains phrases (strings)
        this.matePool = [];
        this.mutationRate = mutationRate;
        this.bestFitness = 0;
        this.bestPhrase = "";
        this.totalGenerations = 0;
        // Stopping criterion
        this.minFitness = minFitness;
    }

    clearMatePool () {
        this.matePool = [];
    }

    addIndividual(newIndividual) {
        this.individuals.push(newIndividual);
    }

    evaluate() {
        let fitness = 0;
        for (let i = 0; i < this.size; i++) {
            fitness = this.individuals[i].fitnessFunct(this.target);
            // Update best fitness and best phrase
            if (fitness > this.bestFitness) {
                this.bestFitness = fitness;
                this.bestPhrase = this.individuals[i].getGenotype();
            }
        }
        // Stopping criterion
        if (this.bestFitness < this.minFitness) {
            return true;
        }
        else {
            return false;
        }
    }

    buildMatePool() {
        for (let i = 0; i < this.size; i++) {
            let n = Math.round(this.individuals[i].getFitness() * 100);
            for (let j = 0; j < n; j++) {
                this.matePool.push(this.individuals[i].phrase);
            }
        }
    }

    reproduce() {
        // Create new generation
        for (let i = 0; i < this.size; i++) {
            // Pick 2 parents
            let a, b, child, midpoint;
            while (true) {
                // Index of parentA
                a = getRandomIntInclusive(0, this.matePool.length - 1);
                // Index of parentB
                b = getRandomIntInclusive(0, this.matePool.length - 1);
                // Be sure you have picked two unique parents (phrases)
                if (this.matePool[a] === this.matePool[b]) {
                    continue;
                }
                else {
                    break;
                }
            }
            // Crossover
            child = this.crossover(a, b);
            // Mutation
            this.mutation(child);
            // The new child is part of the new population
            this.individuals[i] = child;
        }
        this.totalGenerations += 1;
    }

    crossover(a, b) {
        let child = new Individual(this.target.length);
        child.setGenotype("");
        let midpoint = getRandomIntInclusive(0, this.target.length-1);

        for (let i = 0; i < this.target.length; i++) {
            if (i < midpoint) {
                child.phrase = child.phrase + this.matePool[a].charAt(i);
            }
            else {
                child.phrase = child.phrase + this.matePool[b].charAt(i);
            }
        }
        return child;
    }

    mutation(individual) {
        for (let i = 0; i < this.target.length; i++) {
            // The block inside the conditional statement would be executed 1% of the time.
            if(Math.random() < this.mutationRate) {
                // replace char with a new random character
                individual.phrase = individual.phrase.substr(0, i) + String.fromCharCode(getRandomIntInclusive(32, 128)) + individual.phrase.substr(i + 1);
            }
        }
    }

}

我有以下 DOM 元素:

// Shows the current generation
var totalGenerationsHTML = $('#total-generations');
// Shows the best phrase so far
var bestPhraseHTML = $('#best-phrase');
// Shows the best fitness so far
var bestFitnessHTML = $('#best-fitness');
// Shows the result of the reproduction process (child)
var processingHTML = $('#processing');

以及以下代码部分:

var condition = population.evaluate();

while (condition) {
    // Processing
    population.buildMatePool();
    population.reproduce();
    population.clearMatePool();
    condition = population.evaluate();
}

我需要在每次迭代中更新 DOM 元素的值。我使用 setInterval()setTimeout() 尝试了不同的循环实现,但输出不同步。任何帮助都会很有用。

附:我是 JavaScript 新手。如有错误请见谅。

【问题讨论】:

  • 这里有上下文会很好,因为没有任何意义。请提供您从中复制此科学怪人代码的所有链接。请解释你认为它应该做什么。

标签: javascript dom


【解决方案1】:
while (condition) {}

所谓的阻塞代码,因为该循环运行时没有给浏览器实际呈现结果的机会,您将看不到任何内容,并且可能 UI 冻结。

您需要使用setTimeoutsetInterval 或推荐的动画requestAnimationFrame

但输出不同步

更改页面上的 DOM 和可见的东西是一个异步过程,当 Js 运行时,浏览器不会重新绘制。 while 循环正在运行 JS。

更多详细信息请查看here

【讨论】:

  • 感谢requestAnimationFrame() 的建议。我进行了研究,结果证明这是更新 DOM 的最佳方式。
【解决方案2】:

@philipp 是对的。 requestAnimationFrame() 是解决方案。

基本上requestAnimationFrame()是:

  1. 与浏览器重绘同步(setTimeoutsetInterval 不同步)
  2. 针对动画进行了优化
  3. 以屏幕允许的速度运行
  4. 电池节电器

以下 HTML/JS/CSS sn-p 演示了requestAnimationFrame() 的使用。

var currentPos = -200;

var element = document.getElementById("heading");

// Animation loop
function moveRight() {
  currentPos += 5;
	heading.style.left = currentPos + "px";
	window.requestAnimationFrame(moveRight);
	if(currentPos >= 800) {
	  currentPos = -200;
	}
}

moveRight();
h1 {
  position: relative;
  border: 5px solid black;
  text-align: center;
  width: 200px;
}

div {
  width: 800px;
  height: 400px;
  background-color: lime;
  margin: 0 auto;
  overflow: hidden;
}
<!DOCTYPE html>
<html>
	<head>
		<title>Animation Loops</title>
	</head>
	<body>
		<div>
			<p>requestAnimationFrame()</p>
			<ol>
				<li>Synchronized with browser repaint</li>
				<li>Optimized for animation</li>
				<li>Runs as fast as the screen will allow</li>
				<li>Battery saver</li>
			</ol>
			<p>
				Traditionally to create an animation in JavaScript, we relied 
				on setTimeout() called recursively or setInterval() to 
				repeatedly execute some code to make changes to an element 
				frame by frame, such as once every 50 milliseconds. What we 
				specify as the delay (ie: 50 milliseconds) inside these 
				functions are often times not honoured due to changes in user 
				system resources at the time, leading to inconsistent delay 
				intervals between animation frames.
			</p>	
			<p>
				<strong>DO NOT</strong> use setInterval() or setTimeOut() for 
				animations, use requestAnimationFrame() instead.
			</p>
			<h1 id="heading">Animation Loops</h1>
		</div>
	</body>
</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 2021-05-30
    • 1970-01-01
    • 2016-04-09
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多