iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
0
自我挑戰組

每天來點 Vue.js 吧系列 第 14

Vue 雙向數據綁定的語法糖 v-model ✔︎

很久以前做的 form 練

使用表單元件 <textarea><input><select> 時,通常需要用戶的輸入資料或者設定預設選擇,這個時候可以使用 v-modal 進行 雙向數據綁定,一旦用戶對表單元件輸入內容,v-modal 會針對表單元件的類型自動監聽不同輸入事件,進一步更新 data 數據。雖然 v-modal 本身看似神奇,但本身其實是透過監聽用戶的輸入事件進一步更新資料,是一種 語法糖

除此之外,一旦使用了 v-modal,所有表單元件的初始值如 valuecheckedselected 都會被忽略,v-modal 會使用 data 數據來源作為初始值來源,若是需要設定表單元件的初始值,應該要在 data 數據中聲明!

<input type="text">

對於 <input type="text"> 表單元件,v-model 使用 input 事件進行監聽,一旦用戶輸入觸發 input 事件,data 中的 message 資料便會改變。

程式碼

<input type="text" v-model="message">
<p>message: {{ message }}</p>

使用中文輸入法的細節

使用 中文輸入法 在此使用 v-model 不會在輸入過程中更新 data 中的 message,會等到輸入完成 enter 後才會更新 data 中的 message
可以看到輸入完 ㄋㄧˇ 後,data 中的 message 沒有馬上更新

若是需要對 中文輸入法 實時更新 data 中的 message,請自行監聽 input 事件:
這時候 ㄋ一 隨輸入更新了(不過目前還沒遇過此需求,好奇會在哪種需求中使用到 XD

程式碼

<input type="text" :value="message" @input="message = $event.target.value">
<p>message: {{ message }}</p>

<textarea>

對於 <textarea> 表單元件,v-model 使用 input 事件進行監聽,一旦用戶輸入觸發 input 事件,data 中的 message 資料便會改變。

<textarea v-model="message"></textarea>
<p>message: {{ message }}</p>

<input type="checkbox"> 複選框

對於 checkboxv-model 使用 change 事件以及checked property,一旦用戶輸入觸發 change 事件,data 中的 checked 資料便會改變。

單個複選框

單個複選框的值要綁定 truefalse

<input type="checkbox" v-model="checked">
<p> checked: {{ checked }}</p>

多個複選框

對於多個複選框,需要綁定到 Arrayv-model 會取複選框的 value 更新到 data names 中。

<label for="a">a</label>
<input type="checkbox" value="a" v-model="names">
<label for="b">b</label>
<input type="checkbox" id='b' value="b" v-model="names">
<label for="c">c</label>
<input type="checkbox" id="c" value="c" v-model="names">
<p> names: {{ names }}</p>
const vm = new Vue({
  el: ".app",
  data: {
    names: []
  }
});

單選按鈕

對於 <input type="radio"> 表單元件,v-model 使用 change 事件進行監聽,一旦用戶輸入觸發 change 事件,data 中的 picked 資料便會改變。

<label for="A">One</label>
<input id="A" type="radio" value="One" v-model="picked">
<label for="B">Two</label>
<input id="B" type="radio" value="Two" v-model="picked">
<p> picked: {{ picked }}</p>

<select>

對於 <select>v-model 使用 change 事件進行監聽,一旦用戶輸入觸發 change 事件,data 中的 select 資料便會改變。

<select v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
</select>
<span> selected: {{ selected }}</span>

多選時

多選時綁定 Array

<select multiple v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
</select>
<span> selected: {{ selected }}</span>

修飾符

v-model 有三個修飾符,分別為 .lazy.number.trim,分別有下列功用:

.lazy

在使用文本輸入框、多行文本輸入框時,v-model 會在觸發 input 事件後同步更新 data 內數據,使用該修飾符,data 內數據會更改為在 change 事件後同步。

change 事件基於表單元件的不同,觸發時機也不同,在 <input type="text"><textarea> 元件,被觸發的時機為當值被修改且失去焦點後。

原先在觸發 input 後便會同步更改 data 中的數據。

加上 .lazy 後,我們可以看見當輸入文字且 失去焦點 後,data 中的數據才被同步。


補充 inputchange 事件:

要理解兩者的不同,可以先來看一下 WHATWG 規範中對於 inputchange 事件的描述:

The input event fires whenever the user has modified the data of the control. The change event fires when the value is committed, if that makes sense for the control, or else when the control loses focus. In all cases, the input event comes before the corresponding change event (if any).

簡單來說,一旦用戶更改了表單元件的值,變會在該元件觸發 input 事件;當表單元件的值被 commit(MDN 翻譯成 提交修改),便會在該元件觸發 change 事件,所有的 input 事件都會在 change 事件前觸發。

除此之外,還要注意對於不同類型的 表單元件,觸發 change 的時機並不相同:

  • input 元件 typeradiochackbox 時,元件若是為 checked 狀態便會觸發 change 事件。
  • input 元件 typetext 或是為 <textarea> 元件,當值被修改且失去焦點,便會觸發 change 事件。
  • 當用戶顯示提交改變時。

.number

該功能可以將用戶的輸入值轉換成 number,若是無法透過 parseFloat() 轉換成 number 型別,會返回原先的字串值。

一般來說透過 input 取得的值皆為 string

再添加前,若是我們使用 v-model 綁定兩筆資料,並且輸入 數字 相加他們,會看到字串相加:

使用 .number 將兩筆資料轉換成 number 型別後,可以看到結果為數字相加,而非原先的字串相加:

<input type="text" v-model.number="one"> +
    <input type="text" v-model.number="two"> =
<span>sum: {{ one + two }}</span>

.trim

去頭尾,考慮到用戶輸入時可能會有無用的頭尾空白,可以使用 .trim 去掉頭尾的空白。

以上為此次內容,其實只要知道 v-model 是透過綁定 data 數據以及透過監聽事件改值後,便可以知道 v-model語法糖,另外推推 Vue 提供 v-model 相關的 修飾符,在很多時候用起來都超方便的,那麼話不多說馬上來做個表單吧(笑),我們明天見。

form 寫法推可以看 WHATWG 這一篇


若是文中有任何錯誤、錯字、想討論的內容,歡迎各位大大不吝鞭笞指正、交流分享,筆者不慎感激 ✦ ✦ ✦

▶︎ 筆者 github:https://github.com/YUN-RU-TSENG
▶︎ 老王賣瓜之筆者另一篇鐵人:每天來點 CSS Specification

▶︎ 倘若不斷向深處扎根,似乎就能茁壯成長 - RM


參考資料:

  1. Vuejs.org 2.x
  2. Vue.js: data、v-model 與雙向綁定 | Summer。桑莫。夏天
  3. Vue.js 的黑魔法: 指令 | 重新認識 Vue.js | Kuro Hsu

上一篇
v-for 列表渲染
下一篇
Vue components 組件的抽象概念 ✏︎
系列文
每天來點 Vue.js 吧30

尚未有邦友留言

立即登入留言