本篇為官方文件 Migration from Vue 2 筆記。
元件上的 v-model 指令
Vue 3.x 語法變化概述:
- 用於自定義元件時,
v-model
prop 和 event 預設名稱已更改:- prop:
value
->modelValue
; - event:
input
->update:modelValue
。
- prop:
v-bind
的.sync
修飾符號和元件的model
選項已移除,使用v-model
搭配參數即可替代。- 現在可以在同一個元件上使用多個
v-model
進行雙向綁定。 - 現在可以自定義
v-model
修飾符號。
1. 2.x 語法
在 Vue 2.x 的元件上使用 v-model
等同綁定 value
prop 和 input
事件:
|
|
若不希望使用預設的 value
和 input
事件,可以使用 model
選項來設定 prop 和 event 名稱,避免不同的元件上的語意衝突。
|
|
如果不只一個 prop 需要雙向綁定,就需要借助另一個與 v-model
非常相似的 v-bind.sync
。詳細說明可以參考 Vue2.x - sync 修飾符號。
2. 3.x 語法
由於 v-bind.sync
與 v-model
過於相似,Vue 3.x 將兩者結合,移除了 v-bind
的 sync
修飾符號,現在可以使用多個 v-model
指令。
元件 v-model
指令中的 prop 和 event 預設名稱也已更改,避免與需要用到 value
prop 的標籤衝突:
- prop:
value
->modelValue
; - event:
input
->update:modelValue
。
|
|
但要注意的是,Vue 3.x 新增了 emits
選項,除了 prop 需要宣告還有 event。
若要修改預設名稱,將不再使用 model
選項,而是將一個參數傳遞給 model
:
|
|
CodePen Demo:Vue 3.x - v-model 參數
使用多個 v-model
指令:
|
|
在 Vue 3.x 除了可以使用內建修飾符號,還可以自定義修飾符號。
添加到元件 v-model
的修飾符號會透過 modelModifiers
prop 提供給元件。modelModifiers
prop 預設為空物件,當 v-model
使用自定義修飾符號時,modelModifiers
會包含自定義修飾符號名稱屬性,舉例來說 v-model.capitalize=""
就會是 { capitalize: true }
。
接著我們就可以在事件處理函式中檢查是否有使用自定義修飾符號。
CodePen Demo:Vue 3.x - v-model 修飾符號
對於帶參數的 v-model
,自定義修飾符號生成的 prop 將會是 arg + "Modifiers"
,例如 v-model:description.capitalize=""
,生成 prop 名稱為 descriptionModifiers
。
key attribute
- 對於
v-if
/v-else
/v-else-if
的各分支項key
將不再是必須的,因為現在 Vue 會自動生成唯一的key
。- 如果你手動提供
key
,那麼每個分支必須使用唯一的key
。你不能通過故意使用相同的key
來強制重用分支。
- 如果你手動提供
<template v-for>
的key
應該設置在<template>
標籤上(而不是設置在它的子節點上)。
1. 條件分支
在 Vue 2.x 時,當我們使用 v-if
相關指令時,會需要使用 key
,來獨立 DOM 狀態。
|
|
而 Vue 3.x 則會自動生成唯一的 key
:
|
|
因此不建議再手動提供 key
,若你手動提供,變得每個分支都需要設置 key
。
2. <template> 結合 v-for 指令
在 Vue 2.x 中 <template>
標籤不能擁有 key
。不過你可以為其每個子節點分別設置 key
。
|
|
在 Vue 3.x 中 key
則應該被設置在 <template>
標籤上。
|
|
v-if 與 v-for 的優先級對比
1. 2.x 語法
2.x 版本中在一個元素上同時使用 v-if
和 v-for
時,v-for
會優先作用。
2. 3.x 語法
3.x 版本中,則剛好相反,v-if
總是優先於 v-for
生效。
不過本來就不建議同時使用這兩個指令,因此沒啥影響。
v-bind 合併行為
v-bind
的綁定順序會影響渲染結果。
1. 2.x 語法
在 2.x 版本中,如果一個元素同時定義了 v-bind="object"
語法和相同的 property,那麼這個單獨的 property 一定會覆蓋 object
中的綁定。
|
|
2. 3.x 語法
在 3.x 版本中,宣告綁定的順序會決定如何合併:
|
|
移除 v-on.native 修飾符號
1. 2.x 語法
想要在子元件的根元素上監聽原生 DOM 事件可以使用 v-on
指令的 .native
修飾符號,否則預設情況下只有通過 this.$emit
觸發。
|
|
|
|
CodePen Demo:Vue 2.x - native 修飾符號
2. 3.x 語法
在 3.x 版本中,已移除 v-on
指令的 .native
修飾符號。
因為 3.x 版本新增了 emits
選項,只有在 emits
選項中定義的事件會做為自訂義事件,而未定義的事件則會作為原生事件添加到子元件的根元素中。
|
|
|
|
CodePen Demo:Vue 3.x - 原生事件
v-for 中的 Ref 陣列
v-for
中的 ref
不再註冊 ref 陣列。
1. ref
ref
可以用來取得 DOM 元素,也就是將元素註冊在 $refs
物件。詳細可以參考 Vue2.x API ref。
若是在使用 v-for
指令元素上使用 ref
,將會建立包含所有元素的陣列。但當使用巢狀 v-for
時,$refs
的結構就會變得相當不直覺,元素陣列是分開的:
<!-- Vue 2.x -->
<div v-for="x of 3" ref="xDoms">
<div v-for="y of 3" ref="yDoms">{{ x * y }}</div>
</div>
CodePen Demo:Vue2.x - 巢狀 ref
2. 3.x 語法
因此 Vue 3.x 將不再自動建立陣列,需要搭配 v-bind
指令將 ref
綁定到一個更靈活的函式上。
<!-- Vue 3.x -->
<div v-for="n of 10" :ref="setDoms">n</div>
|
|
我們可以透過該函式將取得的元素迭代放置在一個陣列或物件中。
CodePen Demo:Vue3.x - ref
如果 v-for 的元素是動態的,要確保在每次更新之前重置容器:
|
|
CodePen Demo:Vue3.x - ref 更新