全面剖析Vue3 全新特性 defineModel
一、defineModel 是什么?
defineModel 是 Vue 3.4 引入的一個編譯器宏,用于簡化組件雙向數(shù)據(jù)綁定的實現(xiàn)。它是對 v-model 指令在組件上使用的語法糖,讓開發(fā)者可以更簡潔地實現(xiàn)父子組件之間的雙向數(shù)據(jù)同步。
二、核心優(yōu)勢
- 代碼簡化:減少樣板代碼,不再需要手動定義
props和emit - 類型安全:完美支持 TypeScript 類型推斷
- 功能強大:內(nèi)置支持修飾符處理
- 開發(fā)體驗:更直觀的雙向綁定實現(xiàn)方式
三、基礎用法
3.1 基本實現(xiàn)
子組件實現(xiàn):
<template>
<div>
<input
type="text"
:vaule="modelValue"
@input="e => modelValue = e.target.value"
>
</div>
</template>
<script setup>
import { defineModel } from 'vue';
const modelValue = defineModel()
</script>父組件使用:
<script setup >
import myinput from '@/components/my-input.vue';
import { ref } from 'vue'
const txt = ref('123456')
</script>
<template>
<div>
<myinput v-model="txt"></myinput>
{{ txt }}
</div>
</template>3.2 等效的傳統(tǒng)實現(xiàn)
在沒有 defineModel 時,我們需要這樣寫:
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input
type="text"
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
>
</template>四、高級特性
4.1 多 v-model 支持
子組件:
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
</script>
<template>
<input v-model="firstName">
<input v-model="lastName">
</template>父組件:
<UserForm v-model:first-name="firstName" v-model:last-name="lastName" />
4.2 類型定義
<script setup lang="ts">
// 帶類型的 defineModel
const count = defineModel<number>('count', { default: 0 })
// 復雜類型
interface User {
name: string
age: number
}
const user = defineModel<User>('user')
</script>4.3 修飾符處理
父組件使用修飾符:
<MyInput v-model.trim="text" />
子組件處理修飾符:
<script setup>
const [modelValue, modifiers] = defineModel({
// setter 中可以訪問 modifiers
set(value) {
if (modifiers.trim) {
return value.trim()
}
return value
}
})
</script>五、實現(xiàn)原理
defineModel 在編譯階段會被轉(zhuǎn)換為:
- 一個
modelValueprop - 一個
update:modelValue事件 - 一個計算屬性,提供 getter 和 setter
編譯后的代碼類似于:
const props = defineProps({
modelValue: { type: String }
})
const emit = defineEmits(['update:modelValue'])
const modelValue = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})六、最佳實踐
命名規(guī)范:
單一模型使用 defineModel()
多個模型使用 defineModel('name')
默認值設置:
const value = defineModel({
default: ''
})復雜驗證:
const age = defineModel({
type: Number,
validator: (v) => v >= 0
})與原生輸入組件結(jié)合:
<input :value="modelValue" @input="modelValue = $event.target.value" >
七、對比傳統(tǒng)方式
| 特性 | defineModel | 傳統(tǒng)方式 |
|---|---|---|
| 代碼量 | 1行聲明 | 需要props + emit |
| 類型支持 | 自動推斷 | 需要手動定義 |
| 多模型支持 | 參數(shù)指定名稱 | 需多個props/emit |
| 修飾符處理 | 內(nèi)置支持 | 需要手動實現(xiàn) |
| 兼容性 | Vue 3.4+ | 所有Vue3版本 |
八、實際案例
自定義計數(shù)器組件
Counter.vue:
<script setup>
const count = defineModel<number>({ default: 0 })
</script>
<template>
<button @click="count--">-</button>
<span>{{ count }}</span>
<button @click="count++">+</button>
</template>父組件使用:
<template>
<Counter v-model="quantity" />
<p>當前數(shù)量:{{ quantity }}</p>
</template>
<script setup>
const quantity = ref(1)
</script>九、注意事項
- 版本要求:必須使用 Vue 3.4 或更高版本
- 單向數(shù)據(jù)流:雖然看起來像雙向綁定,但仍然是單向數(shù)據(jù)流
- 復雜邏輯:對于復雜場景,仍然可以使用傳統(tǒng)方式
- Ref解包:在模板中會自動解包,無需
.value
defineModel 是 Vue 3.4 中非常實用的新特性,它大幅簡化了組件雙向綁定的實現(xiàn)代碼,同時保持了類型安全和靈活性。對于新項目,強烈推薦使用這種方式來實現(xiàn) v-model 功能。
到此這篇關(guān)于全面剖析Vue3 全新特性 defineModel 的文章就介紹到這了,更多相關(guān)vue defineModel 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue.js中關(guān)于偵聽器(watch)的高級用法示例
Vue.js 提供了一個方法 watch,它用于觀察Vue實例上的數(shù)據(jù)變動。下面這篇文章主要給大家介紹了關(guān)于Vue.js中關(guān)于偵聽器(watch)的高級用法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2018-05-05
解決vue prop傳值default屬性如何使用,為何不生效的問題
這篇文章主要介紹了解決vue prop傳值default屬性如何使用,為何不生效的問題。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Vue用v-for給循環(huán)標簽自身屬性添加屬性值的方法
這篇文章主要介紹了Vue用v-for給循環(huán)標簽自身屬性添加屬性值的方法,文中大家給大家列舉了三種方法 ,需要的朋友可以參考下2018-10-10

