I have a simple Vue app that is supposed to add a number to a Set when you click the "Add to Set" button --
<div id="app">
<input type="number" placeholder="enter a number" v-model="n">
<button type="button" @click.prevent="addToSet()">Add to Set</button>
</div>
new Vue({
el: "#app",
data: {
n: null,
nSet: new Set()
},
methods: {
addToSet: function() {
this.nSet.add(this.n);
console.log(this.n + ' added to Set');
}
},
watch: {
nSet: function (newVal, oldVal) {
console.log(newVal);
}
}
});
Why is nothing logged in the console by the watch?
I have a simple Vue app that is supposed to add a number to a Set when you click the "Add to Set" button --
https://codepen.io/jerryji/pen/mKqNvm?editors=1011
<div id="app">
<input type="number" placeholder="enter a number" v-model="n">
<button type="button" @click.prevent="addToSet()">Add to Set</button>
</div>
new Vue({
el: "#app",
data: {
n: null,
nSet: new Set()
},
methods: {
addToSet: function() {
this.nSet.add(this.n);
console.log(this.n + ' added to Set');
}
},
watch: {
nSet: function (newVal, oldVal) {
console.log(newVal);
}
}
});
Why is nothing logged in the console by the watch?
Share Improve this question asked Jun 18, 2018 at 13:49 Jerry JiJerry Ji 3861 gold badge3 silver badges15 bronze badges 3-
1
Is there any reason why you're using
Set
overArray
? If the sole purpose is to ensure uniqueness, you can easily check withindexOf
before pushing. AFAIK there is no easy way to watch forSet
changes. – Terry Commented Jun 18, 2018 at 14:06 - Because Set is required in the actual code. The codepen is just a stripped down example. But I got your point. Thanks – Jerry Ji Commented Jun 18, 2018 at 14:30
- Wondering if Sets are non reactive within Vue ponents. – Francis Leigh Commented Jun 18, 2018 at 14:44
3 Answers
Reset to default 4Saving and re Set
ting the Set using the .values()
method on Set
worked for me and i didn't have to use $forceUpdate
Using $forceUpdate
might be the more sensible way to go though. In some use cases in the past i have found forcing ponents to update to be problematic.
new Vue({
el: "#app",
data: {
n: null,
nSet: new Set()
},
methods: {
addToSet: function() {
let set = this.nSet;
let newSet = set.add(this.n)
this.nSet = new Set(newSet.values())
}
},
watch: {
nSet: function (newVal, oldVal) {
console.log('newVal', ...newVal);
}
}
});
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<input type="number" placeholder="enter a number" v-model="n">
<button type="button" @click.prevent="addToSet()">Add to Set</button>
<p>n = {{ n }}</p>
</div>
Vue adds special handling for Arrays, but not for Sets. As a result, Vue doesn't automatically detect changes to Set membership. You can force an update, though
this.nSet.add(this.n);
this.$forceUpdate();
It's because Vue doesn't support Set, Map, WeakSet and WeakMap. And it's because browsers didn't support these structures well. Especially WeakMap. But... They decided to support these structures. Maybe in version 3 - when they decide to drop support for older browsers. So, for now use an object, add properties with Vue.$set()
and watch for changes with deep: true
.