在 Vue 開發中,v-model
是實現表單輸入和應用狀態之間雙向綁定的關鍵指令。Vue 3 對 v-model
進行了重大改進,使其更加靈活和強大。本文將深入探討 Vue 3 中 v-model
的工作原理、新特性以及最佳實踐。
1. v-model 基礎
1.1 什么是 v-model
v-model
是 Vue 提供的一個語法糖,它本質上結合了 v-bind
和 v-on
:
<input v-model="message">
等價于:
<input :value="message"@input="message = $event.target.value"
>
1.2 基本用法
在表單元素上使用 v-model
非常簡單:
<template><input v-model="text" placeholder="請輸入"><p>你輸入的內容是: {{ text }}</p>
</template><script setup>
import { ref } from 'vue'const text = ref('')
</script>
2. Vue 3 中的 v-model 改進
2.1 多個 v-model 綁定
Vue 3 允許在單個組件上使用多個 v-model
:
<UserNamev-model:first-name="firstName"v-model:last-name="lastName"
/>
子組件實現:
<script setup>
defineProps({firstName: String,lastName: String
})defineEmits(['update:firstName', 'update:lastName'])
</script><template><input:value="firstName"@input="$emit('update:firstName', $event.target.value)"/><input:value="lastName"@input="$emit('update:lastName', $event.target.value)"/>
</template>
2.2 v-model 修飾符
Vue 3 支持自定義 v-model
修飾符。例如,創建一個 capitalize
修飾符:
<MyComponent v-model.capitalize="myText" />
子組件處理:
<script setup>
const props = defineProps({modelValue: String,modelModifiers: { default: () => ({}) }
})const emit = defineEmits(['update:modelValue'])function emitValue(e) {let value = e.target.valueif (props.modelModifiers.capitalize) {value = value.charAt(0).toUpperCase() + value.slice(1)}emit('update:modelValue', value)
}
</script><template><input :value="modelValue" @input="emitValue" />
</template>
3. 不同表單元素的使用
3.1 文本輸入
<input v-model="text" type="text">
3.2 多行文本
<textarea v-model="message"></textarea>
3.3 復選框
單個復選框綁定到布爾值:
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
多個復選框綁定到數組:
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
3.4 單選按鈕
<input type="radio" id="one" value="One" v-model="picked">
<input type="radio" id="two" value="Two" v-model="picked">
3.5 選擇框
單選:
<select v-model="selected"><option disabled value="">請選擇</option><option>A</option><option>B</option><option>C</option>
</select>
多選(綁定到數組):
<select v-model="selected" multiple><option>A</option><option>B</option><option>C</option>
</select>
4. v-model 修飾符
Vue 提供了一些內置修飾符來修改 v-model
的行為:
4.1 .lazy
將 input
事件改為 change
事件:
<input v-model.lazy="msg">
4.2 .number
自動將用戶輸入轉為數字:
<input v-model.number="age" type="number">
4.3 .trim
自動去除用戶輸入的首尾空白:
<input v-model.trim="msg">
5. 在組件中使用 v-model
5.1 基本實現
子組件:
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script><template><input:value="modelValue"@input="$emit('update:modelValue', $event.target.value)"/>
</template>
父組件:
<CustomInput v-model="searchText" />
5.2 帶參數的 v-model
子組件:
<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script><template><inputtype="text":value="title"@input="$emit('update:title', $event.target.value)"/>
</template>
父組件:
<MyComponent v-model:title="bookTitle" />
6. 高級技巧
6.1 自定義輸入組件
創建一個帶驗證的輸入組件:
<!-- ValidatedInput.vue -->
<script setup>
import { computed } from 'vue'const props = defineProps({modelValue: String,required: Boolean,minLength: Number
})const emit = defineEmits(['update:modelValue'])const error = computed(() => {if (props.required && !props.modelValue) {return '此字段為必填項'}if (props.minLength && props.modelValue?.length < props.minLength) {return `至少需要 ${props.minLength} 個字符`}return null
})function handleInput(e) {emit('update:modelValue', e.target.value)
}
</script><template><input :value="modelValue" @input="handleInput" /><div v-if="error" class="error">{{ error }}</div>
</template>
使用:
<ValidatedInput v-model="username" :required="true" :minLength="5"
/>
6.2 組合式 API 中的 v-model
使用 computed
實現更復雜的邏輯:
<script setup>
import { computed } from 'vue'const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])const value = computed({get() {return props.modelValue},set(value) {emit('update:modelValue', value)}
})
</script>
7. 性能考慮
- 避免大型表單的深度響應式:對于大型表單,考慮使用淺響應式或手動管理狀態
- 防抖處理:頻繁的輸入可以使用防抖優化性能
- 虛擬滾動:對于大量選項的選擇框,考慮使用虛擬滾動
8. 常見問題解答
Q: v-model 和 sync 修飾符有什么區別?
A: 在 Vue 2 中,.sync
修飾符用于雙向綁定,Vue 3 中已統一使用帶參數的 v-model
。
Q: 為什么我的 v-model 在自定義組件上不工作?
A: 確保子組件正確接收 modelValue
prop 并發出 update:modelValue
事件。
Q: 如何處理 v-model 的初始值?
A: 確保父組件為 v-model
綁定的數據提供初始值。
9. 總結
Vue 3 的 v-model
提供了更靈活、更強大的雙向數據綁定能力。通過理解其工作原理和各種使用場景,開發者可以構建更復雜、更高效的表單交互。關鍵點包括:
v-model
是:value
和@input
的語法糖- Vue 3 支持多個
v-model
綁定 - 可以創建自定義修飾符
- 在組件中使用需要正確實現 prop 和 emit
掌握這些概念將大大提升你在 Vue 開發中的效率和代碼質量。