Considering following HTML code:
<div id="app">
<comp :is_checked="is_checked" v-on:ch="function(x){is_checked_2=x}"></comp>
<p>{{ is_checked_2 }}</p>
</div>
<script src="app.js"></script>
and app.js:
var tm = `<div>
<input type="checkbox" v-model="is_checked"
v-on:change="$emit('ch',is_checked)"
>{{ is_checked }}
</div>`
Vue.component('comp', {
template: tm,
props: ["is_checked"]
})
new Vue({
el: "#app",
data: function() {
return {
is_checked: null,
is_checked_2: null
};
}
});
If we replace is_checked_2=x
by console.log(x)
in v-on:ch="function(x){...}
, everything works correct and v-model
is changing is_checked
when input checkbox value changes.
Also if we don't send the value of variable by props and define it locally in component, everything works correct.
It seems that changing the parent Vue's object variable is regenerating the whole HTML of component where the value of variable is sent by props and the variable is reset there immediately after firing the event inside template. It is causing that functions triggered by events don't change component's variables.
Is it a bug in Vue.js?
To make it more clear, the behavior is following: changing whatever Vue parent value that is not bound and however related to the component (no props, no slots) results at resetting all values in the component that are bound by props. Following only occurs if we reactivelly write to parent/main HTML using modified parent variable, we can achieve that by placing {{ .... }}
there. This seems to be the bug.
Example: Vue has variables a
and b
. We place {{ a }}
to the main code. The value of variable b
is sent by props to component and matched to variable c
. With the time we are changing that value of variable c
inside the component. In one moment we decide to change value of a
and it results by "forgetting" current state of c
and it is reset to initial state by invoked props.
To summarize: the bug itself gets stuck that props should be reactivelly invoked only if corresponding parent variable is changed and not if whatever parent variable changes and at the same time they modify HTML code.
This issue doesn't have nothing to do with event listeners neither events, because it is possible to replicate it without using them.
Conclusion:
{{ is_checked_2 }}
or {{ '',is_checked_2 }}
or {{ '',console.log(is_checked_2) }}
after changing value of is_checked_2
is causing rerendering the whole top Vue component having is_checked
as variable and it is resetting child component variable, because it has the same name. The solution is never using the same name for child and parent component variables bound by props. This is issue of Vue/props architecture how it was designed.