Reputation: 834
I am using Vue for the first time, and am confused about why one of my Vue objects keeps updating when the data changes, and the other Vue object won't.
I have a JavaScript module like this to basically just hold data:
var MyModule = (function(){
const info = {
requestCount: 20,
arrayOfItems: []
}
return info;
})();
I have this html:
<span id='requestCounter' class='badge'>{{count}}</span>
<table id='vueTable'><tr v-for="item in items"><td>{{item.description}}</td></tr></table>
And lastly, I have this JavaScript file to do everything:
window.onload = function(){
var mainTable = new Vue({
el: '#vueTable',
data: {
items: MyModule.arrayOfItems
}
});
var requestCounterVue = new Vue({
el: '#requestCounter',
data: {
count: MyModule.requestCount
}
});
}
On the first runthrough, everything works as intended. Changing the MyModule.arrayOfItems
works correctly, the table updates depending on what is in the array. However, changing MyModule.requestCount
doesn't do anything. Can anybody tell me what I'm doing wrong here?
(Note, my example is simplified to make my question easier)
Upvotes: 1
Views: 426
Reputation: 82459
Roy is exactly right. I'm just leaving this here because I was typing while he answered, and possibly more explanation couldn't hurt.
MyModule
doesn't become reactive just because you use it to initialize values in your Vues. I expect the reason arrayOfItems
is working the way you expect is because you are not actually setting it to a new array, you are mutating the existing array.
For example, your Vue using the array is defined here.
var mainTable = new Vue({
el: '#vueTable',
data: {
items: MyModule.arrayOfItems
}
});
If you add a value to MyModule.arrayOfItems
like this
MyModule.arrayOfItems.push('my new value')
then your Vue will show the new value. This is because mainTable.items
and MyModule.arrayOfItems
are pointers to the same array.
If instead, however, you modified MyModule.arrayOfItems
like this
MyModule.arrayOfItems = ['my','new','array']
Then mainTable
will not show the updated array. This is because you've changed it to a completely different array. In other words, MyModule.arrayOfItems !== mainTable.items
.
This is also the reason changing MyModule.count
to a new value is not reflected in requestCounterVue
. MyModule.count
is a primitive value and when you initialized requestCounterVue
with count
, it used a copy of the value and made the copy reactive. Changing MyModule.count
will have no effect.
If you wanted to see the changes reflected, what you might do is initialize your Vues this way
var mainTable = new Vue({
el: '#vueTable',
data: MyModule
});
When the Vue is instantiated, MyModule
will be turned into a reactive object and changes will be reflected for both count
and arrayOfItems
.
Upvotes: 2
Reputation: 43881
You are initializing the data in your Vue objects from MyModule. This does not make MyModule a proper store or controller. The weird behavior is not that requestCount
doesn't react, but that arrayOfItems
does.
The reason the array behaves as it does is that objects are passed by reference, so when you initialize items
, Vue gets hold of the actual array object and does its magic on it. Effectively, MyModule provides an external handle to your Vue data.
requestCount
, on the other hand, is a simple value, not an object, so it is passed by value, and there is absolutely no relationship between the member in MyModule and the data item in requestCounterVue
.
Upvotes: 2