📖 概述
useModel()
?是 Vue 3.4+ 版本中引入的一個組合式 API 輔助函數,它是驅動?defineModel()
?的底層實現。這個函數主要用于在非單文件組件中實現雙向數據綁定,特別是在使用原始的?setup()
?函數時。
?? 重要提示:如果使用?<script setup>
,應當優先使用?defineModel()
。
🎯 基本概念
什么是 useModel?
useModel()
?是一個用于創建雙向數據綁定的底層輔助函數。它允許子組件直接修改父組件傳遞的 prop 值,而無需手動觸發 emit 事件。
與 defineModel 的關系
特性 | defineModel() | useModel() |
---|---|---|
使用場景 | <script setup> ?語法糖 | 底層實現 |
代碼簡潔度 | ????? | ??? |
控制精細度 | ??? | ????? |
推薦程度 | 應當優先使用 | 特定場景使用 |
- ??
defineModel()
?是?<script setup>
?中的語法糖,更簡潔易用,應當優先使用 - 🔧?
useModel()
?是底層實現,適用于非單文件組件或需要更精細控制的場景
🔧 函數簽名
function useModel(props: Record<string, any>,key: string,options?: DefineModelOptions
): ModelRef;type DefineModelOptions<T = any> = {get?: (v: T) => any;set?: (v: T) => any;
};type ModelRef<T, M extends PropertyKey = string, G = T, S = T> = Ref<G, S> &[ModelRef<T, M, G, S>, Record<M, true | undefined>];
📋 參數說明
參數 | 類型 | 必需 | 描述 |
---|---|---|---|
props | Record<string, any> | ? | 組件的 props 對象 |
key | string | ? | 要綁定的 prop 名稱 |
options | DefineModelOptions | ? | 自定義 getter 和 setter 函數 |
🎯 使用場景
1?? 非單文件組件中的雙向綁定
當使用傳統的?
setup()
?函數而不是?<script setup>
?時,useModel()
?是創建雙向綁定的最佳選擇。在?<script setup>
?中,請優先使用?defineModel()
。
2?? 需要自定義轉換邏輯
當需要對傳入和傳出的值進行轉換時,可以使用?
options
?參數。
3?? 復雜的組件庫開發
在開發可復用的組件庫時,可能需要更精細的控制。
💻 代碼示例
🚀 基礎用法
export default {props: ["count"],emits: ["update:count"],setup(props) {const count = useModel(props, "count");// 直接修改值會自動觸發 emitcount.value = 1;return {count,};},
};
🔄 帶自定義轉換的用法
export default {props: ["value"],emits: ["update:value"],setup(props) {const modelValue = useModel(props, "value", {// 自定義 getter:將字符串轉換為數字get: (v) => (v ? parseInt(v) : 0),// 自定義 setter:將數字轉換為字符串set: (v) => v.toString(),});return {modelValue,};},
};
🎨 在模板中使用
<template><div><input :value="count" @input="count = $event.target.value" /><button @click="count++">增加</button></div>
</template><script>
export default {props: ["count"],emits: ["update:count"],setup(props) {const count = useModel(props, "count");return {count,};},
};
</script>
?? 與 defineModel 的對比
? defineModel (推薦用于 script setup)
<script setup>
const count = defineModel("count");
</script>
🔧 useModel (適用于 setup 函數)
export default {props: ["count"],emits: ["update:count"],setup(props) {const count = useModel(props, "count");return { count };},
};
?? 注意事項
🔢 版本要求
- 🚫 僅在 Vue 3.4+ 版本中可用
- ? 確保項目依賴版本滿足要求
📝 Props 和 Emits 聲明
與?defineModel()
?不同,使用?useModel()
?時需要手動聲明:
- 📦 props 數組或對象
- 📤 emits 數組或對象
🛡? 類型安全
在 TypeScript 項目中,建議為 props 和 emits 提供完整的類型定義:
interface Props {count: number;
}interface Emits {"update:count": [value: number];
}export default {props: ["count"] as PropType<Props>,emits: ["update:count"] as Emits,setup(props: Props) {const count = useModel(props, "count");return { count };},
};
🎯 最佳實踐
1?? 優先使用 defineModel
在?
<script setup>
?中,應當優先使用?defineModel()
,代碼更簡潔易讀。?只有在以下情況下才考慮使用?useModel()
:
- 🔧 使用傳統的?
setup()
?函數 - ?? 需要更精細的控制和自定義轉換邏輯
- 📚 開發復雜的組件庫
2?? 合理使用自定義轉換
只在確實需要數據轉換時使用?
options
?參數,避免過度復雜化。
3?? 保持一致性
在同一個項目中,保持雙向綁定的實現方式一致。
4?? 類型安全
在 TypeScript 項目中,始終提供完整的類型定義。
? 常見問題
Q: 什么時候使用 useModel 而不是 defineModel?
A: 在?
<script setup>
?中,應當優先使用?defineModel()
。?只有在以下情況下才使用?useModel()
:
- 🔧 使用傳統的?
setup()
?函數而不是?<script setup>
- ?? 需要自定義 getter/setter 進行復雜的數據轉換
- 🎛? 需要更精細的控制邏輯
Q: useModel 是否支持多個雙向綁定?
A: 是的,可以多次調用?
useModel()
?來創建多個雙向綁定。
Q: 如何處理復雜的驗證邏輯?
A: 可以在?
options.set
?中添加驗證邏輯,如果驗證失敗可以拋出錯誤或返回原值。
📝 總結
useModel()
?是 Vue 3.4+ 中實現雙向數據綁定的強大工具,特別適用于非單文件組件。重要原則:在?<script setup>
?中,應當優先使用?defineModel()
,代碼更簡潔易讀。?只有在使用傳統的?setup()
?函數或需要更精細控制時,才考慮使用?useModel()
。理解這兩個 API 的使用場景和差異,有助于在 Vue 3 項目中更好地實現組件間的數據通信。
?Vue 3 useModel vs defineModel:選擇正確的雙向綁定方案 - 高質量源碼分享平臺-免費下載各類網站源碼與模板及前沿技術分享