im learning vue js following a channel on YT, the video was sent last year, so i think its not working due to some changes on VueJS itself, but it would be great if you guys could help me with this
codeio link: http://codepen.io/myrgato/pen/BWWxdQ
HTML
<script src="https://unpkg.com/vue@2.2.2"></script>
<div id="app">
<button @click="increment">Increment</button>
<p>Counter: {{counter}}</p>
<p>Clicks: {{clicks}}</p>
</div>
JS
new Vue({
el: '#app',
data: {
counter: 0,
clicks: 0
},
methods: {
increment(){
this.clicks++;
}
},
computed: {
counter(){
return this.clicks * 2;
}
}
});
its supposed to calculate the amount of clicks, then use a computed proprerty to display a counter that equals clicks times two, but for some reason it isnt working..
Short but the full answer:
Never use the same name for data
variable and computed
.
Think about data & computed as the same object, so names can't be duplicated.
Here is a working solution. The trick is to:
- use a different name for the computed property (here
counter2
)
- and to use a lambda function with a single parameter (here
x
) instead of this
.
new Vue({
el: '#app',
data: {
counter: 0,
clicks: 0
},
methods: {
increment() {
this.clicks++;
}
},
computed: {
counter2: x => x.clicks * 2
}
});
<script src="https://unpkg.com/vue@2.2.2"></script>
<div id="app">
<button @click="increment">Increment</button>
<p>Counter: {{counter2}}</p>
<p>Clicks: {{clicks}}</p>
</div>
Since I wasn't sure of why this happened I ran two tests on jsFiddle:
sample A:
sample B
Here you would notice that in sample B the order of execution is:
- Data properties get added first.
- The created hook is invoked.
- The computed property calculates the value of counter
In sample A, the step 3 never happens.
In vue2.1.0, you would get a warning like :
Vue warn: existing instance property "haveTrigger" will be overwritten by a computed property with the same name.
Further checking in the docs I found that this warning is suppressed in vue 2.2.2 hence you never received it, but along with it I found this interesting piece:
Props and computed properties are now defined on a component's prototype instead of as self properties on each instance. This avoids many calls to Object.defineProperty and improves component initialization performance. This will only affect you if you rely on hasOwnProperty checks on props and computed properties, which should be extremely rare, but we are documenting it here to be explicit about the change.
Source
var fancyConstructor = function () {
this.value = 5
}
var instance = new fancyConstructor()
fancyConstructor.prototype.value = 5000
fancyConstructor.prototype.someOtherValue = 5000
console.log(instance.value)
console.log(instance.someOtherValue)
you can also go deep down in each component to find that there are indeed computed properties set to counter
.
The above snippet will illustrate what happens if a property by the same name is there on the object as well as the prototype.