When you set the value of Vue.prototype.user, Vue is not expecting that value to be bound to the DOM, so it won't be reactive. You maybe have seen global services set up this way (like Vue.prototype.$http or similar), but these objects are not being bound directly to the DOM.
The most straight-forward way to maintain a reactive globally-accessible object is to use Vuex.
You can create a store to contain the user object:
const store = new Vuex.Store({
state: { user: getUser() }
})
And register the store by passing the store object to the root Vue instance:
new Vue({
el: '#app',
store
})
Then, in whichever components you need to access the user object, you can define a computed user property via the Vuex.mapState help function:
computed: Vuex.mapState(['user'])
Here's a simple example:
function getUser() {
return {
firstName: 'John',
lastName: 'Doe'
}
}
const store = new Vuex.Store({
state: { user: getUser() },
})
Vue.component('user-card', {
template: `<h1>{{user.firstName}} {{user.lastName}}</h1>`,
computed: Vuex.mapState(['user'])
})
new Vue({
el: '#app',
store,
computed: Vuex.mapState(['user'])
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
<div id="app">
<user-card></user-card>
<input type="text" v-model="user.firstName" />
<input type="text" v-model="user.lastName" />
</div>
If you don't want to have to add the Vuex library, (and you really don't mind each of your components having access to the user object) you could also use a mixin:
let user = getUser();
Vue.mixin({
data() {
return { user }
}
})
This way, all of your Vue instances will have access to a reactive user object pointing to the user object initially set in you main.js file.
Here's an example of that:
function getUser() {
return {
firstName: 'John',
lastName: 'Doe'
}
}
let user = getUser();
Vue.mixin({
data() {
return { user }
}
})
Vue.component('user-card', {
template: `<h1>{{user.firstName}} {{user.lastName}}</h1>`,
})
new Vue({
el: '#app',
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id="app">
<user-card></user-card>
<input type="text" v-model="user.firstName" />
<input type="text" v-model="user.lastName" />
</div>