Skip to content

原生 v-model(表单输入绑定)

单行文本

v-model 会绑定 value 属性并监听 input 事件。

vue
<script setup>
import { ref } from 'vue'

const msg = ref('hello')
</script>

<template>
  <div>msg: {{ msg }}</div>

  <!-- v-model -->
  <input v-model="msg" />

  <!-- value + @input -->
  <input :value="msg" @input="(e) => (msg = e.target.value)" />
</template>

多行文本

v-model 会绑定 value 属性并监听 input 事件。

vue
<script setup>
import { ref } from 'vue'

const msg = ref('hello')
</script>

<template>
  <div>msg: {{ msg }}</div>

  <!-- v-model -->
  <textarea v-model="msg" />

  <!-- value + @input -->
  <textarea :value="msg" @input="(e) => (msg = e.target.value)" />
</template>

单选按钮

v-model 会绑定 checked 属性并监听 change 事件。

vue
<script setup>
import { ref } from 'vue'

const picked = ref('')
</script>

<template>
  <div>picked: {{ picked }}</div>

  <!-- v-model -->
  <label>
    One
    <input type="radio" value="One" v-model="picked" />
  </label>
  <label>
    Two
    <input type="radio" value="Two" v-model="picked" />
  </label>

  <!-- value + @change -->
  <label>
    One
    <input type="radio" value="One" :checked="picked === 'One'" @change="(e) => (picked = e.target.value)" />
  </label>
  <label>
    Two
    <input type="radio" value="Two" :checked="picked === 'Two'" @change="(e) => (picked = e.target.value)" />
  </label>
</template>

复选框

复选框有两种情况:

  1. 单个复选框,绑定布尔类型值。
  2. 多个复选框,绑定到同一个数组或集合的值。

单个复选框

v-model 会绑定 checked 属性并监听 change 事件。

vue
<script setup>
import { ref } from 'vue'

const checked = ref(false)
</script>

<template>
  <div>checked: {{ checked }}</div>

  <!-- v-model -->
  <input type="checkbox" id="checkbox" v-model="checked" />

  <!-- checked + @change -->
  <input type="checkbox" id="checkbox" :checked="checked" @change="(e) => (checked = e.target.checked)" />
</template>

值绑定

默认情况下,v-model 绑定的值(toggle)只会是布尔值 truefalse

true-valuefalse-value 是 Vue 特有的 attributes,仅支持和 v-model 配套使用。toggle 属性的值会在选中时被设为 'yes',取消选择时设为 'no'

template
<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no" />

多个复选框

v-model 会绑定 checked 属性并监听 change 事件。

vue
<script setup>
import { ref } from 'vue'

const checkedNames = ref([])

// --- checked + @change ---
const checkedNamesSet = new Set([])
const handleCheckboxChange = (e) => {
  const { checked, value } = e.target
  if (checked) {
    checkedNamesSet.add(value)
  } else {
    checkedNamesSet.delete(value)
  }
  checkedNames.value = Array.from(checkedNamesSet)
}
</script>

<template>
  <div>checkedNames: {{ checkedNames }}</div>

  <!-- v-model -->
  <label>
    <input type="checkbox" value="Jack" v-model="checkedNames" />
    Jack
  </label>
  <label>
    <input type="checkbox" value="John" v-model="checkedNames" />
    John
  </label>
  <label>
    <input type="checkbox" value="Mike" v-model="checkedNames" />
    Mike
  </label>

  <!-- checked + @change -->
  <label>
    <input type="checkbox" value="Jack" :checked="checkedNames.includes('Jack')" @change="handleCheckboxChange" />
    Jack
  </label>
  <label>
    <input type="checkbox" value="John" :checked="checkedNames.includes('John')" @change="handleCheckboxChange" />
    John
  </label>
  <label>
    <input type="checkbox" value="Mike" :checked="checkedNames.includes('Mike')" @change="handleCheckboxChange" />
    Mike
  </label>
</template>

选择器

选择器有两种情况:

  1. 单选
  2. 多选 (值绑定到一个数组)

单选

v-model 会绑定 value 属性并监听 change 事件。

vue
<script setup>
import { ref } from 'vue'

const selected = ref('')
</script>

<template>
  <div>selected: {{ selected }}</div>

  <!-- v-model -->
  <select v-model="selected">
    <option value="">Please select one</option>
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
  </select>

  <!-- value + @change -->
  <select :value="selected" @change="(e) => (selected = e.target.value)">
    <option value="">Please select one</option>
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
  </select>
</template>

多选

v-model 会绑定 value 属性并监听 change 事件。

vue
<script setup>
import { ref } from 'vue'

const multiSelected = ref([])

const handleSelectChange = (e) => {
  const selected = Array.from(e.target.selectedOptions).map((opt) => opt.value)
  multiSelected.value = selected
}
</script>

<template>
  <div>Selected: {{ multiSelected }}</div>

  <!-- v-model -->
  <select v-model="multiSelected" multiple>
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
  </select>

  <!-- value + @change -->
  <select :value="multiSelected" @change="handleSelectChange" multiple>
    <option value="A">A</option>
    <option value="B">B</option>
    <option value="C">C</option>
  </select>
</template>

修饰符

.lazy

默认情况下,v-model在每次 input 事件后更新数据v-model.lazy 会将行为改为 在每次 change 事件后更新数据

template
<!-- 在 "change" 事件后同步更新而不是 "input" -->
<input v-model.lazy="msg" />

.number

v-model.number 会尝试把用户的输入值转换为一个数字,如果该值无法被 parseFloat() 处理,那么将返回原始值。

template
<input v-model.number="age" />

提示

number 修饰符会在输入框有 type="number" 时自动启用。

.trim

v-model.trim 会自动去除用户输入内容中两端的空格:

template
<input v-model.trim="msg" />

基于 MIT 许可发布