本篇為官方文件 Migration from Vue 2 筆記。
元件上的 v-model 指令
Vue 3.x 語法變化概述:
- 用於自定義元件時,
v-modelprop 和 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 更新