Skip to content Skip to sidebar Skip to footer

Execute Non-function Code Before A Function Call

I'm working on a simple Vue game app with buttons to decrease player or 'demon' health by a random number within a range when a button is clicked. In my Vue instance is a method at

Solution 1:

Actually I wanted to mark this as duplicate - but then i realized that most solutions suggest the usage of setTimout - wich is creating an unneeded racecondition between javascript and browser rendering.

When you mutatate object properties in the scope of vue - meaning they are reactive - and you want to wait for a dom update and a dom render there is following you can do:

First await vm.$nextTick() which will calculate the dom and then give the browser time to breath with doublerequestAnimationFrame.

And as an implementation example:

Vue.skipFrame = function(){

  returnnewPromise(resolve => {
    requestAnimationFrame(() =>requestAnimationFrame(resolve)
    )
  })
}
let app = newVue({
  el: '#app',
  data: {
    monster: 10,
    hero: 100
  },

  methods: {
    attack() {
      this.monster = Math.max(
        this.monster - (Math.random() * 10)|0, 
        0
      )
      
      
      this.checkWin()
    },
    asynccheckWin(){
      awaitthis.$nextTick()
      awaitVue.skipFrame()
      if(this.monster == 0){
        confirm('You won! Again?') ?
        this.start():
        this.quit()
      }
    },
    start() {
      this.hero = 100;
      this.monster = 100;
    },
    quit(){
      this.monster = 1000;
      
    }
  }

  });
.as-console-wrapper{
  height: 0px!important
}
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script><divid="app"><h1>Monster HP: {{monster}}</h1><h1>Hero HP: {{hero}}</h1><button @click="attack">Attack</button></div>

Solution 2:

The following answer doesn't work on chrome and for that i submitted an issue ticket at github

Like @Phil suggests using $nextTick will solve your problem ..it is basically a method that contains a callback that gets executed after the DOM is updated in case of synchronous Or returns a promise on the asynchronous one (im using the async here) and the reason why your confirm is executed before the DOM update even though it is inside a condition loop of the updated state (dh || ph <=0) is because confirm will essentially pause the rendering of HTML and run though the entire JavaScript file before they resume the HTML rendering...and concerning your bar dynamic width i added some condition so if the player / deamon health is below 0 the health bar will be empty .

checkWin: function() {
  if (this.demonHealth <= 0) {
    this.$nextTick().then(() => {
      if (confirm('You won! New game?')) {
        this.startGame();
      } else {
        this.gameIsRunning = false;
      }
    })
   returntrue;
  } else {
    if (this.playerHealth <= 0) {
      this.$nextTick().then(() => {
        if (confirm('You lost. New game?')) {
          this.startGame();
        } else {
          this.gameIsRunning = false;
        }
      })
     returntrue;
    }
  }
}
<div:style="{ width: playerHealth >= 0 ?  playerHealth + '%' : 0  }"><div:style="{ width: demonHealth >= 0 ?  demonHealth + '%' : 0   }">

here is a Demo : codepen

Post a Comment for "Execute Non-function Code Before A Function Call"