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>