改变 innerHTML 只工作一次

Changing innerHTML only works once

我正在尝试在 HTML 中制作记分牌,其中 javascript 函数可以更改不同玩家的分数。但是,除一名玩家外,所有玩家的分数都无法正确显示。

HTML:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    <div id="scoreboard"></div>
    <script type="text/javascript" src="main.js"></script>
</body>
</html>

Javascript:

function Player(ID) {
    this.ID = ID;

    var scoreboard = document.getElementById("scoreboard");

    //Create a <p> in scoreboard with "Player n:" in it, and then
    //create a <span> with the score and a unique ID to use for getting and setting
    scoreboard.innerHTML += "<p>Player " + this.ID + ":" + "<span id=\"PlayerScore" + this.ID + "\">0</span></p>";

    this.scoreElement = document.getElementById("PlayerScore" + this.ID); //set score element

    //Getter and setter for score
    this.getScore = function() {return Number(this.scoreElement.innerHTML);}
    this.setScore = function(scoreIn) {this.scoreElement.innerHTML = scoreIn.toString();}
}

我使用以下 Javascript 测试此代码:

var player1 = new Player(1);
var player2 = new Player(2);
var player3 = new Player(3);

player1.setScore(player1.getScore() + 1);
player2.setScore(player2.getScore() + 1);
player3.setScore(player3.getScore() + 1);

执行此操作后,生成的网页中的记分牌显示为:

Player 1:0
Player 2:0
Player 3:1

但是,它应该是

Player 1:1
Player 2:1
Player 3:1    

有什么想法吗?为什么只有最后一个有效?我如何直接从 scoreElement 的 InnerHTML 获取和设置有问题吗?跟我的浏览器(firefox)有关系吗?

问题是您使用 innerHTML 附加更多内容,一旦您使用 innerHTML += 它将重新创建所有 dom 元素,因此您创建的 scoreElement 引用以前将不再出现在 dom 树中,这就是为什么它们没有得到更新的原因。

解决方法就是不要使用.innerHTML追加内容,而是可以创建dom个元素,然后调用appendChild()方法将其添加到父元素中,如

function Player(ID) {
  this.ID = ID;

  var scoreboard = document.getElementById("scoreboard");

  var playerElement = document.createElement('p');
  this.scoreElement = document.createElement('span');
  this.scoreElement.innerHTML = 0;
  playerElement.appendChild(document.createTextNode("Player " + this.ID + ":"));
  playerElement.appendChild(this.scoreElement);
  scoreboard.appendChild(playerElement)

  //Getter and setter for score
  this.getScore = function() {
    return Number(this.scoreElement.innerHTML);
  }
  this.setScore = function(scoreIn) {
    this.scoreElement.innerHTML = scoreIn.toString();
  }
}

var player1 = new Player(1);
var player2 = new Player(2);
var player3 = new Player(3);

player1.setScore(player1.getScore() + 1);
player2.setScore(player2.getScore() + 1);
player3.setScore(player3.getScore() + 1);
<div id="scoreboard"></div>


作为 @dandavis said in the ,您可以做的另一个调整是

function Player(ID) {
  this.ID = ID;

  var scoreboard = document.getElementById("scoreboard");

  var playerElement = document.createElement('p');
  playerElement.innerHTML = "Player " + this.ID + ":" + '<span>0</span>';
  this.scoreElement = playerElement.querySelector('span');
  scoreboard.appendChild(playerElement)

  //Getter and setter for score
  this.getScore = function() {
    return Number(this.scoreElement.innerHTML);
  }
  this.setScore = function(scoreIn) {
    this.scoreElement.innerHTML = scoreIn.toString();
  }
}

var player1 = new Player(1);
var player2 = new Player(2);
var player3 = new Player(3);

player1.setScore(player1.getScore() + 1);
player2.setScore(player2.getScore() + 1);
player3.setScore(player3.getScore() + 1);
<div id="scoreboard"></div>

这个问题,每次你调用构造函数,它都会重建scoreboard.innerHTML,意味着它的所有子元素都被删除并重建,

所以只有在您的最后一个实例中,this.scoreElement 才不会重建。

您可以在每次获得或设置分数时使用 appendChildgetElementById 解决此问题

function Player(ID) {
    this.ID = ID;

    var scoreboard = document.getElementById("scoreboard");

    //Create a <p> in scoreboard with "Player n:" in it, and then
    //create a <span> with the score and a unique ID to use for getting and setting
    scoreboard.innerHTML += "<p>Player " + this.ID + ":" + "<span id=\"PlayerScore" + this.ID + "\">0</span></p>";


    //Getter and setter for score
    this.getScore = function() {return Number(document.getElementById("PlayerScore" + this.ID).innerHTML);}
    this.setScore = function(scoreIn) { document.getElementById("PlayerScore" + this.ID).innerHTML = scoreIn.toString();}
}


var player1 = new Player(1);
var player2 = new Player(2);
var player3 = new Player(3);



player1.setScore(player1.getScore() + 1);
player2.setScore(player2.getScore() + 1);
player3.setScore(player3.getScore() + 1);
<div id="scoreboard"></div>