Reputation: 45
Experimenting with adding watchers dynamically in Vue.js. Disconnect between desired/actual results is shown in the commented portion below. Occasional/amateur coder here; I suspect my problem is less with Vue and more with understanding of JavaScript fundamentals. Thanks in advance!
new Vue({
el: '#app',
data: {
a: 1,
b: 2,
c: 3
},
methods: {
setUpWatchers(array) {
for (var i in array) {
var key = array[i];
this.$watch(key, function(newValue) {
console.log(key + ': ' + newValue);
//desired output is:
// a: 4
// b: 5
// c: 6
//actual output is:
// c: 4
// c: 5
// c: 6
});
}
}
},
created() {
this.setUpWatchers(['a', 'b', 'c']);
this.a = 4;
this.b = 5;
this.c = 6;
}
});
Upvotes: 2
Views: 1390
Reputation: 82499
You're correct, this is a classic javascript "gotcha".
Variables declared with var
have a function scope. When using var
all of the functions declared in your loop (you are declaring 3; the handlers for $watch) are using the same
variable, which, after the loop is complete, points to c
.
A quick fix is to declare your variables with let
. let
has block scope, so each function declared in your loop will have access to just the copy of the variable as it existed at the time the function was created.
Here is a working example.
new Vue({
el: '#app',
data: {
a: 1,
b: 2,
c: 3
},
methods: {
setUpWatchers(array) {
for (let i in array) {
let key = array[i];
this.$watch(key, function(newValue) {
console.log(key + ': ' + newValue);
});
}
}
},
created() {
this.setUpWatchers(['a', 'b', 'c']);
this.a = 4;
this.b = 5;
this.c = 6;
}
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app"></div>
Ideally, these days, you should be using let
or const
and almost never var
. There are numerous resources that are available that will describe the differences.
Upvotes: 1