0👍
For your situation you can simply use .sync
modifier to avoid mutating props directly. Sync modifier means your prop receiver component (child) receives props data from parent and generates an event when parent must change passed value.
And parent component should bind prop with ‘.sync’ modifier that means auto subscription on child event with update.
More info you can read here
This way your code will work fine
Vue.component('like',{
template: '#like' ,
props: ['lval','lname','lstep','lclass'],
methods:{
changeCounter : function(step){
this.$emit('update:lval', this.lval + parseInt(step));
}
}
});
new Vue({
el: '#app',
data:{
counterlike: 0,
counterdislike: 0
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<like lname="Like" lstep="1" :lval.sync="counterlike" lclass="btn-success"></like>
<like lname="Dislike" lstep="-1" :lval.sync="counterdislike" lclass="btn-danger"></like>
<br>
{{ counterlike + counterdislike }}
</div>
<template id="like">
<button :class="['btn',lclass]" @click="changeCounter(lstep)" >{{ lname + ' ' + lval }}</button>
</template>
0👍
There is a reason why props can’t be mutated directly, this way the information has one-way flow, from parent to child and not the other way around.
0👍
True two-way bindings can’t be achieved, but the child can emit an event with needed info to the parent, and the latter could update bound variable.
Since 2.3.0 Vue has a special .sync
modifier to do just that, and here is your modified snippet using .sync
modifier. Note, that changeCounter
method doesn’t change lval
directly, but emits an event.
Here
Vue.config.productionTip = false;
Vue.component('like', {
template: '#like',
props: ['lval', 'lname', 'lstep', 'lclass'],
methods: {
changeCounter: function(step) {
const newlval = this.lval + parseInt(step);
this.$emit('update:lval', newlval);
}
}
});
new Vue({
el: '#app',
data: {
counterlike: 0,
counterdislike: 0
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<like lname="Like" lstep="1" :lval.sync="counterlike" lclass="btn-success"></like>
<like lname="Dislike" lstep="-1" :lval.sync="counterdislike" lclass="btn-danger"></like>
<br> {{ counterlike + counterdislike }}
</div>
<template id="like">
<button :class="['btn',lclass]" @click="changeCounter(lstep)" >{{ lname + ' ' + lval }}</button>
</template>