Skip to content

双向绑定

什么是双向绑定

在前端处理表单时,常常需要将表单输入的内容同步给 Javascript 变量,或者将 Javascript 变量的值同步给表单输入。这种双向的数据同步,就是双向绑定。

WARNING

  • v-model 只能用在表单元素上。
  • v-model 会忽略所有表单元素的 valuecheckedselected 特性的初始值,而总是将 Vue 实例的数据作为数据来源。
  • v-model 会根据所使用的元素自动使用对应的 DOM 属性和事件组合:
    • <input><textarea> 元素绑定 value 属性并监听 input 事件;
    • checkboxradio 绑定 checked 属性并监听 change 事件;
    • <select> 绑定 value 属性并监听 change 事件。

文本框

vue
<template>
    <div class="div-box">
        <!-- 单行文本框 -->
        <p>Single Line Message is: {{ singleLineMsg }}</p>
        <input v-model="singleLineMsg" placeholder="edit me" />

        <!-- 多行文本框 -->
        <p style="white-space: pre-line;">Multiple Line Message is: {{ multipleLinesMsg }}</p>
        <textarea v-model="multipleLinesMsg" placeholder="add multiple lines"></textarea>
    </div>
</template>

<script setup>
import { ref } from 'vue'
const singleLineMsg = ref('');
const multipleLinesMsg = ref('');
</script>

复选框

vue
<template>
    <div class="div-box">
        <!-- 单一复选框,绑定布尔值 -->
        <input type="checkbox" id="checkbox" v-model="checked" />
        <label for="checkbox">{{ checked }}</label>

        <!-- 多个复选框,绑定数组 -->
        <div>Checked names: {{ checkedNames }}</div>

        <input type="checkbox" id="jack" value="Jack" v-model="checkedNames" />
        <label for="jack">Jack</label>

        <input type="checkbox" id="john" value="John" v-model="checkedNames" />
        <label for="john">John</label>

        <input type="checkbox" id="mike" value="Mike" v-model="checkedNames" />
        <label for="mike">Mike</label>
    </div>
</template>

<script setup>
import { ref } from 'vue'
const checked = ref(false);
const checkedNames = ref([]);
</script>
vue
<template>
    <div class="div-box">
        <input type="checkbox" id="checkbox" :true-value="dynamicTrueValue" :false-value="dynamicFalseValue"
            v-model="toggle" />
        <label for="checkbox">{{ toggle }}</label>
    </div>
</template>

<script setup>
import { ref } from 'vue'
const dynamicFalseValue = 'no';
const dynamicTrueValue = 'yes';
const toggle = ref(dynamicFalseValue);
</script>

单选框

vue
<template>
    <div class="div-box">
        <div>Picked: {{ picked }}</div>

        <input type="radio" id="one" value="One" v-model="picked" />
        <label for="one">One</label>

        <input type="radio" id="two" value="Two" v-model="picked" />
        <label for="two">Two</label>
    </div>
</template>

<script setup>
import { ref } from 'vue'
const picked = ref('');
</script>
vue
<template>
    <div class="div-box">
        <div>Picked: {{ pick }}</div>

        <input type="radio" id="one" v-model="pick" :value="first" />
        <label for="one">One</label>

        <input type="radio" id="two" v-model="pick" :value="second" />
        <label for="two">Two</label>
    </div>
</template>

<script setup>
import { ref } from 'vue'
const pick = ref('');
const first = 'first';
const second = 'second';
</script>

下拉选框

Details

如果 v-model 表达式的初始值不匹配任何一个选择项,<select> 元素会渲染成一个“未选择”的状态。在 iOS 上,这将导致用户无法选择第一项,因为 iOS 在这种情况下不会触发一个 change 事件。因此,建议提供一个空值的禁用选项。

vue
<template>
    <div class="div-box">
        <!-- 单选 -->
        <div>Selected: {{ selected }}</div>

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

        <!-- 多选 -->
        <div>Selected: {{ multipleSelected }}</div>

        <select v-model="multipleSelected" multiple>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
    </div>
</template>

<script setup>
import { ref } from 'vue'
const selected = ref();
const multipleSelected = ref([]);
</script>
vue
<template>
    <div class="div-box">
        <div>Selected: {{ selected.number }}</div>

        <select v-model="selected">
            <option disabled value="">Please select one</option>
            <option :value="{ number: 123 }">A</option>
            <option :value="{ number: 456 }">B</option>
            <option :value="{ number: 789 }">C</option>
        </select>
    </div>
</template>

<script setup>
import { ref } from 'vue'
const selected = ref({ number: undefined });
</script>