Javascript 在函数调用之前执行非函数代码

Javascript 在函数调用之前执行非函数代码,javascript,vue.js,Javascript,Vue.js,我正在开发一个简单的Vue游戏应用程序,当点击一个按钮时,可以在一定范围内随机减少玩家或“恶魔”的生命值。在我的Vue实例中,有一种方法攻击,用于计算伤害并检查游戏是否结束(如果它导致玩家或恶魔的健康值达到/低于零)。当前,如果它等于或低于零,则会调用JS内置的确认函数来宣布玩家赢了或输了,并询问他们是否想要开始新游戏。不过,我想先检查一下玩家或恶魔的健康状况{ if(this.demonHealth==0){ 如果(确认('你赢了!新游戏?')){ 这个; }否则{ this.gameIsRu

我正在开发一个简单的Vue游戏应用程序,当点击一个按钮时,可以在一定范围内随机减少玩家或“恶魔”的生命值。在我的Vue实例中,有一种方法<代码>攻击,用于计算伤害并检查游戏是否结束(如果它导致玩家或恶魔的健康值达到/低于零)。当前,如果它等于或低于零,则会调用JS内置的确认函数来宣布玩家赢了或输了,并询问他们是否想要开始新游戏。不过,我想先检查一下玩家或恶魔的健康状况{ if(this.demonHealth==0){ 如果(确认('你赢了!新游戏?')){ 这个; }否则{ this.gameIsRunning=false; } 返回; } }); this.playerHealth-=this.calculatedImage(5,12); 这个。分数检查(()=>{ 如果(this.playerHealth==0){ 如果(确认('你输了。新游戏?')){ 这个; }否则{ this.gameIsRunning=false; } } }); }, 计算图像:函数(最小值、最大值){ 返回Math.max(Math.floor(Math.random()*max)+1,min); }, } 编辑:我还在原始代码上尝试了$nextTick(),但效果与以前一样:

checkWin: function() {
  if (this.demonHealth <= 0) {
    this.demonHealth = 0;
    this.$nextTick(function() {
      if (confirm('You won! New game?')) {
        this.startGame();
      } else {
        this.gameIsRunning = false;
      }
      return true;
    });
  } else {
    if (this.playerHealth <= 0) {
      this.playerHealth = 0;
      this.$nextTick(function() {
        if (confirm('You lost. New game?')) {
          this.startGame();
        } else {
          this.gameIsRunning = false;
        }
        return true;
      });
    }
  }
}
checkWin:function(){

如果(this.demonHealth以下答案在
chrome
上不起作用,为此我在github上提交了一个问题

比如@Phil建议使用
$nextTick
可以解决您的问题。它基本上是一个包含回调的方法,在同步的情况下更新DOM后执行回调,或者在异步的情况下返回承诺(我在这里使用异步)以及为什么在DOM更新之前执行
确认
,即使它在更新状态
(dh | | ph)的条件循环中

这里是一个演示:

实际上我想将其标记为重复-但后来我意识到大多数解决方案建议使用
设置超时
-这在javascript和浏览器呈现之间创建了一个不必要的竞争条件

当您在vue范围内更改对象属性(这意味着它们是反应性的)并希望等待dom更新和dom渲染时,可以执行以下操作:

首先
等待vm.$nextTick()
,它将计算dom 然后让浏览器有时间用double
requestAnimationFrame
呼吸

作为一个实施示例:

Vue.skipFrame=function(){
返回新承诺(解决=>{
requestAnimationFrame(()=>
requestAnimationFrame(解析)
)
})
}
让应用程序=新Vue({
el:“#应用程序”,
数据:{
怪物:10,
英雄:100
},
方法:{
攻击(){
this.monster=Math.max(
this.monster-(Math.random()*10)| 0,
0
)
这个是checkWin()
},
异步checkWin(){
等待此消息。$nextTick()
等待Vue.skipFrame()
如果(this.monster==0){
确认('你赢了!又赢了?')?
这个。start():
这个。退出()
}
},
开始(){
这个英雄=100;
这个怪物=100;
},
退出{
这个怪物=1000;
}
}
});
。作为控制台包装器{
高度:0px!重要
}

怪物HP:{{Monster}}
英雄HP:{{Hero}
攻击

这里有很多东西需要尝试和接受,但我认为您希望在
$nextTick
回调中执行
confirm
,例如
this.$nextTick(()=>{if(confirm(…){…})
。请参阅感谢您的建议--我尝试过,效果与以前一样。我编辑了问题以发布我使用的代码。不幸的是,
$nextTick
仍然执行得太快,对话框会中断DOMupdate@Phil我想你用的是chrome,我只是在上面试了一下,但没有用……它在Mozilla上可以用,你的答案是需要考虑的是,
checkWin
不再返回布尔值。事实上,您的方法不返回任何东西check-其目的是不等待浏览器render@Phil一架rAF实际上在当前帧中开火,因此需要一架双rAF来推迟到下一帧。如果这成为一个标准的rAF答案,那就太好了或者DOM更新和对话框(如
alert
confirm
)的问题。回答非常好,比
setTimeout
new Vue({
  el: '#app',
  data: {
    playerHealth: 100,
    demonHealth: 100,
    gameIsRunning: false
  },
  methods: {
    startGame: function() {
      this.gameIsRunning = true;
      this.playerHealth = 100,
      this.demonHealth = 100
    },
    attack: function() {
      this.demonHealth -= this.calculateDamage(3, 10);
      if (this.checkWin()) {
        return;
      }

      this.playerHealth -= this.calculateDamage(5, 12);
      this.checkWin();
    },
    calculateDamage: function(min, max) {
      return Math.max(Math.floor(Math.random() * max) + 1, min);
    },
    checkWin: function() {
      if (this.demonHealth <= 0) {
        // this.demonHealth = 0; <-- applied after confirm();
        if (confirm('You won! New game?')) {
          this.startGame();
        } else {
          this.gameIsRunning = false;
        }
        return true;
      } else {
        // this.playerHealth = 0; <-- applied after confirm();
        if (this.playerHealth <= 0) {
          if (confirm('You lost. New game?')) {
            this.startGame();
          } else {
            this.gameIsRunning = false;
          }
          return true;
        }
      }
    }
  }
});
methods: {
    startGame: function() {
      this.gameIsRunning = true;
      this.playerHealth = 100,
      this.demonHealth = 100
    },
    scoreCheck: function() {
      if (this.demonHealth < 0) {
        this.demonHealth = 0;
      }
      if (this.playerHealth < 0) {
        this.playerHealth = 0;
      }
    },
    attack: function() {
      this.demonHealth -= this.calculateDamage(3, 10);
      this.scoreCheck(() => {
        if (this.demonHealth === 0) {
          if (confirm('You won! New game?')) {
            this.startGame();
          } else {
            this.gameIsRunning = false;
          }
          return;
        }
      });

      this.playerHealth -= this.calculateDamage(5, 12);
      this.scoreCheck(() => {
        if (this.playerHealth === 0) {
          if (confirm('You lost. New game?')) {
            this.startGame();
          } else {
            this.gameIsRunning = false;
          }
        }
      });
    },
    calculateDamage: function(min, max) {
      return Math.max(Math.floor(Math.random() * max) + 1, min);
    },
  }
checkWin: function() {
  if (this.demonHealth <= 0) {
    this.demonHealth = 0;
    this.$nextTick(function() {
      if (confirm('You won! New game?')) {
        this.startGame();
      } else {
        this.gameIsRunning = false;
      }
      return true;
    });
  } else {
    if (this.playerHealth <= 0) {
      this.playerHealth = 0;
      this.$nextTick(function() {
        if (confirm('You lost. New game?')) {
          this.startGame();
        } else {
          this.gameIsRunning = false;
        }
        return true;
      });
    }
  }
}