I'm trying to create a global computed property from within a Vue 3 plugin, so that my property can be used reactively in any component. I am using the standard Vue 3 pattern:
app.config.globalProperties.$foo = ...
This works great to let me access this.$foo
from any component. However, I also want to trigger behavior when this.$foo
is set. But when I try to make it a settable computed property, like this—
app.config.globalProperties.$foo = computed({
get: () => ...
set: () => ...
})
—it doesn't behave like a computed property: If I run this.$foo = 'bar'
from a component, it simply overwrites the property, without triggering the computed setter. (Testing it on a computed without a setter, the property is also simply overwritten, where Vue would normally throw a warning.)
How can I make a global computed with a setter? Is there something I am missing here about how global properties (or computed properties in the Vue 3 composition API) are supposed to work?
computed()
returns a ref
, so its value must be accessed through the .value
property. Setting $foo
directly would just overwrite the reference to some new value instead of modifying the computed
ref's value:
this.$foo = 'bar' // ❌ overwrites the computed ref
this.$foo.value = 'bar' // ✅ sets computed ref's value; triggers setter
You likely need reactivity, and a computed
ref with a getter/setter would need to use another ref
for that:
// main.js
import { computed, ref } from 'vue'
⋮
let foo = ref(123)
app.config.globalProperties.$foo = computed({
get: () => foo.value,
set: value => foo.value = value,
})
// MyComponent.vue
export default {
methods: {
logFoo() {
console.log(this.$foo.value) // => 123
},
updateFoo() {
this.$foo.value++
}
}
}