Skip to content

Vue 3 實戰:掌握 defineModel 輕鬆實現元件 v-model 雙向綁定

在以前的 Vue 版本中,要在元件上實現 v-model 需要手動處理 props (modelValue) 與 emits (update:modelValue),過程相當繁瑣。

自從 Vue 3.4+ 推出了 defineModel 之後,我們可以用更直覺、更簡潔的方式在子元件中建立 雙向綁定 的狀態,讓父子元件之間的數據同步像魔法一樣自然。

基礎語法:從單向變雙向

透過 defineModel(),子元件可以像使用一般的 ref 一樣去修改資料,而這些修改會自動同步回父元件。

下(子)層

js
const counter = defineModel();
html
<input type="button" value="-" @click="counter--" />
<span v-text="counter"></span>
<input type="button" value="+" @click="counter++" />

上(父)層

html
<Child v-model="counter" />

進階實戰:使用物件形式進行嚴謹宣告

就像 props 一樣,defineModel 也支援物件配置,讓您可以針對綁定的資料進行 型別檢查預設值設定必填限制。這在開發多人協作的元件庫時尤為重要。

js
const counter = defineModel({
  required: true, // 規範必須傳入
  type: Number, // 規範必須為數字
  default: 10, // 若父層未傳值時的初始預設值
});

為什麼要使用物件宣告?

  • 安全性:確保傳入的資料型別正確(例如:計數器不應該接收到字串)。
  • 可讀性:其他開發者看到代碼時,能立刻知道這個 v-model 預期的資料格式。
  • 防錯警告:當傳入資料不符合規範時,Vue 會在主控台發出警告。

總結:defineModel 的優勢

  • 簡化代碼:不再需要同時撰寫 propsemits
  • 直覺操作:在子元件中修改 counter.value 就會自動觸發事件通知父層。
  • 完全相容:完美支援 Vue 的響應式系統,讓元件封裝更加模組化。

實戰建議

如果您正在使用 Vue 3.4 以上的版本,請務必將現有的 props + emit 模式遷移至 defineModel,這將顯著減少元件的樣板程式碼。