'Vue 3 setInterval Methods behavior
Env
I have a Vue 3 Application which requires a constant setInterval()
to be running in the background (Game Loop).
I put that in store/index.js
and call it from views/Playground.vue
on mounted()
.
When leaving Playground
i call beforeUnmount()
. Making sure that not multiple setInterval()
are running.
// store/index.js
startGameLoop({ commit, dispatch, getters }) {
commit(
"setIntervalId",
setInterval(() => {
dispatch("addPower", getters["ship/getFuelPerSecond"]);
}, 1000)
);
},
// Playground.vue
beforeUnmount() {
clearInterval(this.intervalId);
}
In the top section of Playground.vue
there is a score displayed and updated within the setInterval()
. I use a library called gsap
to make the changing numbers a bit pleasant for the eye.
<h2>Points: {{ tweened.toFixed(0) }}</h2>
watch: {
points(n) {
console.log("gsap");
gsap.to(this, { duration: 0.2, tweened: Number(n) || 0 });
},
},
Problem
methods
from the Playground.vue
are fired differently and i'm struggling to understand why that is the case.
gsap
the watch
from the gsap
is fired every second like i would expect from the setInterval()
but...
Image
In the center of the Playground i display and image where the src
part is v-bind
to a method called getEnemyShipImage
. In the future i would like to change the displayed enemie ship programmatically - but the method is called 34 times per second. Why is that?
<img
:class="{ flashing: flash }"
@click="fightEnemie()"
:src="getEnemyShipImage()"
alt=""
/>
getEnemyShipImage() {
console.log("image");
return require("@/assets/ships/ship-001.png");
}
Log (Browser)
Solution 1:[1]
moved it to a part without using a method
and switch changing images to a watch
.
data: () => {
return {
...
selectedImages: "",
images: [
require("@/assets/ships/ship-001.png"),
require("@/assets/ships/ship-002.png"),
require("@/assets/ships/ship-003.png"),
],
};
},
// initial value
mounted() {
this.selectedImages =
this.images[Math.floor(Math.random() * this.images.length)];
this.$store.dispatch("startGameLoop");
}
// watch score
watch: {
score() {
this.selectedImages =
this.images[Math.floor(Math.random() * this.images.length)];
},
}
it's not perfect but better as initialy.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Nick |