Vue wrapper example
It behaves that way because of how v-model
works. What you are a looking at is a 2-way binding. Where if the value of selected
in v-model="selected"
changes, the value will be pushed down to the component.
When vm.$emit('input', this.value)
is called, it tells the parent to update whatever variable is listening to changes, in this case selected
, which it turn gets pushed back to the component such that its value gets changed.
To make it simpler to understand, this is the sequence of events:
- select2's value changes
- the select2 value change triggers an event emission
- the parent receives the event and updates
selected
- the component's value gets assigned to the new value of
selected
- the watcher for the value gets triggered and updates select2 with the new value
Good question though.
Caveat: Doing this is understandably poor practice. It will break it sad ways when used with 1-way bindings.
After writing my previous answer, I realized I missed something important: contexts.
On line 5 in the jsfiddle, there is this line:
var vm = this
, why?
This is because later on, when doing vm.$emit
, this.$emit
will not work; the context has been changed.
.on('change', function () { //this = select2 element vm.value // == 1 this.value // == 2 vm.$emit("input", this.value); })
The value on the emit event is not that of the component, but of the select2
element.
While the value
has not yet been changed on the component, the new value has been broadcasted to the parent.
Notice how select2
component used in the template:
<select2 :options="options" v-model="selected"> <option disabled value="0">Select one</option></select2>
In Vue.js using v-model
with components could be simplified to:
<your-component :value="selected" @input="value => { selected = value }"></your-component>
So every time you emit an event from your component the value gets changed at the parent component.