The countdown timer works well but the deep watcher doesnt work. I made the deep watcher log the new value of seconds to console but it doesnt although the countdown timer keeps ticking.
export default defineComponent({
name: 'Countdown',
data() {
return {
date_countdown: new Date('August 16, 2022').getTime(),
date_current: {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
},
getDateDiff(date_countdown: number) {
const date_current = new Date().getTime();
const diff = date_countdown - date_current;
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return { days, hours, minutes, seconds };
},
timer() {
return setInterval(() => {
this.date_current = this.getDateDiff(this.date_countdown);
}, 1000);
},
};
},
watch: {
seconds: {
deep: true,
handler(newVal) {
console.log(newVal); // to test the deep watcher; doesnt log tho
},
},
},
mounted() {
this.timer();
},
beforeUnmount() {
clearInterval(this.timer());
},
});
I'm not sure but maybe since the timer() function changes the value of date_current
instead of changing date_current.seconds
individually, the deep watcher is not triggered?
CodePudding user response:
That because you watch
the seconds
but seconds is not a direct property in the data
or a computed property, If you want to watch the changes on seconds
you need to apply watch
event on date_current
and inside the watch
function get date_current.seconds
.
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "Countdown",
data() {
return {
date_countdown: new Date("August 16, 2022").getTime(),
date_current: {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
},
getDateDiff(date_countdown) {
const date_current = new Date().getTime();
const diff = date_countdown - date_current;
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor(
(diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
);
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return { days, hours, minutes, seconds };
},
timer() {
return setInterval(() => {
this.date_current = this.getDateDiff(this.date_countdown);
}, 1000);
},
};
},
watch: {
date_current: {
deep: true,
handler(newVal) {
console.log(newVal.seconds); // to test the deep watcher; doesnt log tho
},
},
},
mounted() {
this.timer();
},
beforeUnmount() {
clearInterval(this.timer());
},
});
</script>
This is a working code example.
CodePudding user response:
If i'm not mistaken when you make this kind of equation;
this.date_current = this.getDateDiff(this.date_countdown);
watch just loses object reference since you set an entirely new object to it and vue uses proxies for reactive properties. So it loses its prior proxy and sets a new one but it doesn't trigger change. (maybe setting immediate: true
helps but it's not well suited for this case.)
if you watch date_current.seconds
then your watcher watches a primitive value and detects the change. (which is a better way to do it.)
Hope it helps.