TL;DR: The biggest difference is what causes the value change:
input events fire on any value changes
change events fire on direct user-initiated value changes
- (The exact details of this vary between input types)
The most significant difference between these two events is what causes the value change on the <input>.
According to MDN:
The input event fires when the value of an <input>, <select>, or <textarea> element has been changed.
In other words, input fires any time the value changes.
change is a little bit more complicated:
The change event is fired for <input>, <select>, and <textarea> elements when an alteration to the element's value is committed by the user. Unlike the input event, the change event is not necessarily fired for each alteration to an element's value.
In other words, change fires when the user changes the value. In addition, change only generally fires when the ending value is different than the starting one (as its name suggests).
For <input> specifically, the exact timing of the change event depends on the input's type attribute. In general:
- For text-based input types (e.g:
search, text, email, password, etc.):
- When the element loses focus (on blur).
- For inputs that open some sort of interactive menu (e.g.
file, date, color, etc.):
- When the UI element is closed.
- If the type has a direct text input mechanism (like
date), then it also fires on each input of text (e.g. on each typed digit).
- For non-textual inputs that are interactive (e.g.
checkbox, radio, & range):
- When the element is left in a new state after interacting with it (e.g. click, drag, keyboard shortcut trigger).
There are a few elements with their own nuances, but these are true in the general case.
Interactive Demo
new Vue({
el: '#app',
data: {
inputs: [],
changes: [],
types: ['text', 'email', 'color', 'file', 'date', 'range'],
},
methods: {
logEvent(e, index) {
this.$set(this[e.type + 's'], index, e.target.value);
},
},
});
<link href="https://unpkg.com/bootstrap@4/dist/css/bootstrap.min.css" rel="stylesheet"><script src="https://unpkg.com/vue@2/dist/vue.min.js"></script>
<div id="app">
<div class="container mw-100 py-3">
<div v-for="(type, i) in types" class="row mb-2">
<div class="col-2">
<span>{{ type.charAt(0).toUpperCase() + type.slice(1) }}:</span>
</div>
<div class="col-5">
<input :type="type" @input="logEvent($event, i)" @change="logEvent($event, i)" />
</div>
<div class="col-5">
<div class="row">
<div class="col-6 text-break">
<span>Input: <span style="color: red">{{ inputs[i] }}</span></span>
</div>
<div class="col-6 text-break">
<span>Change: <span style="color: blue">{{ changes[i] }}</span></span>
</div>
</div>
</div>
</div>
</div>
</div>