1
votes

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.
1

1 Answers

0
votes

I don't think it's a bug.

You're most likely running into a race condition where your change event gets executed before or in place of the internally attached one (hence the seemingly nullified data binding).

Because v-model is essentially just a syntactic sugar for updating data on user input events. Quoting the docs:

v-model internally uses different properties and emits different events for different input elements:

  • text and textarea elements use value property and input event;
  • checkboxes and radiobuttons use checked property and change event;
  • select fields use value as a prop and change as an event.

You might also want to see "Customizing Component v-model".