i am using vuejs3
with options api
. as shown in the code posted below, i create a compsable class ClsUseStates.js
, in which the value of state
changes every second.
in app.vue
, i instantiated an object of ClsUseStates
and when the button in app.vue
is clicked i call the method useStates
to start generating the different states every second.
i wanted to reflect the changes or the different states occur in ClsUseStates
in app.vue
. to achieve that, in app.vue
i created the variable state
of type ref
the <span> state: {{ state }}</span>
displays the changed states as suppose to be, when i run the code, and click the button, the text changes as follows:
started
processing
successful
but the problem i am facing is, the watch:{ state(oldval, newval) { console.log(oldval); console.log(newval); } }
does not trigger the changes
please let me know why the changes in the value of state
is not reflected in watch
i expect, that whin i click the button, to see the console.log
shows the different values of state
as well
ClsUseStates.js
import { ref } from 'vue'
export default class ClsUseStates {
state = ref('not-satrted');
constructor() {}
useStates() {
setTimeout(() => {
this.setState('started')
}, 1000);
setTimeout(() => {
this.setState('processing')
}, 2000);
setTimeout(() => {
this.setState('successful')
}, 3000);
}
setState(state) {
this.state.value = state;
}
getState() {
return this.state;
}
}
app.vue
<template>
<button @click="onDigitizePolygon()">
click
</button>
<span> state: {{ state }}</span>
</template>
<script>
import {ref} from 'vue'
import ClsUseStates from './composables/ClsUseStates.js'
let cls = new ClsUseStates()
let state = ref('---')
export default {
data() {
return {
state
};
},
name: 'App',
components: {
},
methods: {
onDigitizePolygon() {
cls.useStates()
state.value = cls.getState()
}
},
watch:{
state(oldval, newval) {
console.log(oldval);
console.log(newval);
}
}
}
</script>
2
Answers
i think i found the answer. the
watch
option should have been looked like as follows.state.value
must have been watched notstate
}
The issue you’re facing is due to a subtle misunderstanding of Vue’s reactivity system.
In your
onDigitizePolygon
method, you’re doingstate.value = cls.getState()
. What this does is setstate.value
to the ref returned bygetState()
, not the inner value of that ref.That means
state.value
is now pointing to a completely different ref, but your component’s state is still bound to the original ref(‘—‘).So when
cls
updates its internal state, your component’s state isn’t pointing to that new ref, which is why your watcher never triggers.To fix this, you should point
state.value
to the inner value of the ref returned bygetState
.and
Hope this helps! 🌷