SoFunction
Updated on 2025-03-02

Detailed explanation of the data binding method of Vue form control

Basic usage

You can use the v-model directive to create two-way data binding on form control elements. It automatically selects the correct method according to the control type to update the element. v-model is essentially nothing more than syntactic sugar, which is responsible for listening to user input events to update data

[Note] v-model ignores the initial values ​​of the value, checked, and selected properties of all form elements. Because it will select Vue instance data as the specific value. The initial value should be declared in the data option of the JS component

type:text

<div >
 <input v-model="message" placeholder="edit me">
 <p>Message is: {{ message }}</p>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  message:''
 }
})
</script>

In fact, v-model is syntactic sugar for: value and @input events

<div >
 <input :value="message" placeholder="edit me" @input="message=$">
 <p>Message is: {{ message }}</p>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  message:''
 },
})
</script>

textarea

<div >
 <div>
  <span>Multiline message is:</span>
  <p style="white-space: pre-line">{{ message }}</p>  
 </div>
 <textarea v-model="message" placeholder="add multiple lines"></textarea>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  message:''
 }
})
</script>

[Note] Interpolation in the text area ( <textarea></textarea> ) will not take effect, use v-model instead

type:checkbox

<div >
 <input type="checkbox"  v-model="checked">
 <label for="checkbox">{{ checked }}</label>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  checked:false
 }
})
</script>
<div >
 <div>
  <input type="checkbox"  value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox"  value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox"  value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label> 
 </div>
 <div>
  <span>Checked names: {{ checkedNames }}</span> 
 </div>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  checkedNames:[]
 }
})
</script>

type:radio

<div >
 <div>
  <input type="radio"  value="One" v-model="picked">
  <label for="one">One</label>  
 </div>
 <div>
  <input type="radio"  value="Two" v-model="picked">
  <label for="two">Two</label>  
 </div>
 <div>Picked: {{ picked }}</div>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  picked:''
 }
})
</script>

select

Single choice list

&lt;div &gt;
 &lt;select v-model="selected"&gt;
  &lt;option disabled value=""&gt;Please select&lt;/option&gt;
  &lt;option&gt;A&lt;/option&gt;
  &lt;option&gt;B&lt;/option&gt;
  &lt;option&gt;C&lt;/option&gt;
 &lt;/select&gt;
 &lt;span&gt;Selected: {{ selected }}&lt;/span&gt;
&lt;/div&gt;
&lt;script&gt;
var example = new Vue({
 el: '#example',
 data:{
  selected: ''
 }
})
&lt;/script&gt;

[Note] If the initial value of the v-model expression does not match any options, the <select> element will be rendered in the "unselected" state. In iOS, this will prevent the user from selecting the first option because in this case, iOS does not raise a change event. Therefore, providing disabled options like the above is the recommended practice

Multiple selection list

<div >
 <select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
 </select>
 <span>Selected: {{ selected }}</span>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  selected: []
 }
})
</script>

Dynamic Options

Render with v-for

<div >
 <select v-model="selected">
  <option v-for="option in options" :value="">
   {{  }}
  </option>
 </select>
 <span>Selected: {{ selected }}</span>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  selected: 'A',
  options: [
   { text: 'One', value: 'A' },
   { text: 'Two', value: 'B' },
   { text: 'Three', value: 'C' }
  ]
 }
})
</script>

Bind value

For radio buttons, checkboxes and select list options, the value bound by v-model is usually a static string (there is a logical value for checkboxes)

&lt;!-- When selected,`picked` as a string "a" --&gt;
&lt;input type="radio" v-model="picked" value="a"&gt;
&lt;!-- `toggle` for true or false --&gt;
&lt;input type="checkbox" v-model="toggle"&gt;
&lt;!-- When selected,`selected` as a string "abc" --&gt;
&lt;select v-model="selected"&gt;
 &lt;option value="abc"&gt;ABC&lt;/option&gt;
&lt;/select&gt;

But if you want to bind a value to a dynamic property of the Vue instance, you can use v-bind to implement it, and the value of this property may not be a string

Check box

<div >
 <input type="checkbox" v-model="toggle" :true-value="a" :false-value="b">
 <span>{{ toggle }}</span>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  toggle:'',
  a:true,
  b:false
 }
})
</script>

Radio button

<div >
 <input type="radio" v-model="pick" :value="a">
 <span>{{ pick }}</span>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  pick:'',
  a:true
 }
})
</script>

Select List

<div >
 <select v-model="selected">
  <option :value="{ number: 123 }">123</option>
  <option :value="{ number: 234 }">234</option>
  <option :value="{ number: 345 }">345</option>
 </select>
  <span>Selected: {{  }}</span>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  selected:''
 }
})
</script>

Modifier

.lazy

By default, v-model synchronizes the input box's value and data in the input event, but can add a modifier lazy to be synchronized in the change event

In the following example, the data is only synchronized when the cursor is moved out of the input box.

<div >
 <input ="message" placeholder="edit me">
 <p>Message is: {{ message }}</p>
</div>
<script>
var example = new Vue({
 el: '#example',
 data:{
  message:''
 }
})
</script>

.number

If you want to automatically convert the user's input value to Number type (return to the original value if the conversion result of the original value is NaN), you can add a modifier number to v-model to process the input value

This is usually useful because the value entered in HTML will also always return the string type when type="number"

&lt;div &gt;
 &lt;div&gt;
  &lt;input v-model="age1" type="number"&gt;
  &lt;span&gt;{{type1}}&lt;/span&gt;
  &lt;p&gt;Normal input: {{ age1 }}&lt;/p&gt;  
 &lt;/div&gt;
 &lt;div&gt;
  &lt;input ="age2" type="number"&gt;
  &lt;span&gt;{{type2}}&lt;/span&gt;
  &lt;p&gt;numberModifier input: {{ age2 }}&lt;/p&gt;  
 &lt;/div&gt;
&lt;/div&gt;
&lt;script&gt;
var example = new Vue({
 el: '#example',
 data:{
  age1:'',
  age2:'',
 },
 computed:{
  type1:function(){
   return typeof(this.age1)
  },
  type2:function(val){
   return typeof(this.age2)
  },
 }
})
&lt;/script&gt;

.trim

If you want to automatically filter the beginning and end spaces of user input, you can add the trim modifier to the v-model to filter the input

<div >
 <input ="msg">
 <p>msg is: {{ msg }}</p>
</div>

<script>
var example = new Vue({
 el: '#example',
 data:{
  msg:''
 }
})
</script>

For more information about the data binding method of Vue form control, please click the relevant link below