VueJS $watch $refs
In mounted use code below:
this.$watch(
() => {
return this.$refs.<name>.<data>
},
(val) => {
alert('$watch $refs.<name>.<data>: ' + val)
}
)
There is a work around to this. Consider that JavaScript doesn't create a copy of an array when assigning it to a variable, it merely creates a reference to the original array. Knowing that Vue's $refs are arrays, we can do the following:
<template>
<div>
<ul v-if="showAvailable">
<li v-for="pet in allPets.available" :key="pet.id" ref="pets">
{{ pet.name }}
</li>
</ul>
<ul v-else>
<li v-for="pet in allPets.unavailable" :key="pet.id" ref="pets">
{{ pet.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
props: ['allPets'],
data() {
showAvailable: true // Normally would change from a button or something
shownPets: null // set to null for now
},
mounted() {
this.$set(this.$data, 'shownPets', this.$refs.pets);
},
watch: {
shownPets: {
handler(newVal, oldVal){
// Do something when the DOM changes!
},
deep: true
}
}
}
</script>
And voilà. We set our data shownPets
to our pets $ref
after the component mounts. The reference will hold different elements based on if showAvailable
is true
or false
, and now we can watch for $ref or DOM changes.
No, $refs
are not reactive, watch won't work.
You can $watch
$refs.<name>.<data>
but not $refs.<name>
itself, not to mention $refs
.
https://jsfiddle.net/kenberkeley/9pn1uqam/
const Counter = {
data: () => ({
i: 0
}),
template: `<fieldset>
<p>Counter</p>
<code>i = {{ i }}</code>
<button @click="i += 1"> Add One </button>
</fieldset>`
}
const App = {
components: { Counter },
mounted () {
this.$watch(
() => {
return this.$refs.counter.i
},
(val) => {
alert('App $watch $refs.counter.i: ' + val)
}
)
},
template: `<fieldset>
<p>App</p>
<counter ref="counter" />
</fieldset>`
}
new Vue({
el: '#app',
render: h => h(App)
})