iT邦幫忙

2024 iThome 鐵人賽

DAY 23
1
Modern Web

欸你是要進 Vue 了沒?系列 第 23

欸你是要進 Vue 了沒? - Day23:Vue 表單輸入綁定之 v-model 有你在的宇宙一切都不麻煩了

  • 分享至 

  • xImage
  •  

在 Vue 的宇宙裡,表單輸入綁定不再是令人頭痛的問題!有了 v-model,你只需要一句簡單的指令,就可以讓使用者的輸入與你的應用程式完美同步。無論是輸入框、複選框、還是下拉選單,v-model 都幫你搞定!今天就讓我們來看看這個神奇的綁定指令如何讓一切變得超級簡單吧!😎

前言沒有梗,就還是請語言模型寫。

/images/emoticon/emoticon30.gif

但但但但但是!為什麼需要它呢?

比較 cumbersome 的手動處理

cumbersome,翻譯:笨重的;累贅的;低效的。

當前端處理表單時,若要獲取表單上使用者輸入的值,進而同步到介面或某些邏輯,可能需要手動的賦值、綁定。

這是一個手動處理 將 input 輸入值同步到介面上 的簡單例子:

<script setup>
import { ref } from "vue";

const text = ref("");
</script>
<template>
  <div>
    <input
      :value="text"
      @input="(event) => (text = event.target.value)"
      placeholder="請輸入一些內容..."
    />
    <p>當前輸入的內容是:{{ text }}</p>
  </div>
</template>
  1. 定義 text 為響應式內容 "",將其綁定到模板上 {{ text }}
  2. @inputinput 的監聽事件,若使用者輸入文字,將會觸發 (event) => (text = event.target.value),是一個內聯事件處理器,event 為事件物件,而箭頭函式將會把當下的 event.target.value 「賦值」給 text,達到更新資料的行為。
  3. <input :value="text" />:value 會將 text 綁定到 inputvalue 值上,因此輸入框的資料會和模板上文本插值內容同步。

會藉由以上幾個步驟,達成資料、介面同步的「雙向綁定」效果。

官方提到:手動連接值綁定和更改事件監聽器可能會很麻煩

所以!Vue 傳喚了小幫手 v-model 幫助我們解決這些問題。

v-model

定義

用於實現:表單元素與響應式數據之間的雙向綁定。
讓使用者輸入的內容自動反映到資料中,若有資料的變更也會即時更新到使用者的輸入欄位。

語法

<要綁定的元素 v-model="要與元素綁定的數據">

特性

  1. 會忽略元素上初始的相關屬性,並且始終綁定於響應式狀態。

例如:在 input 上定義了 value 屬性、並且綁定了 v-model

<script setup>
import { ref } from "vue";

const text = ref("");
</script>
<template>
  <input v-model="text" value="會忽略我"> 
  <p>目前輸入的內容是:{{ text }}</p>
</template>

Vue 會自動忽略綁定的 value 屬性,而永遠指向 v-model 綁定的響應式狀態。

  1. 根據所綁定的元素,自動對應綁定的屬性、監聽事件。
所綁定的元素 對應屬性 監聽事件
input text value input
textarea value input
checkbox checked change
radio checked change
select value change

MDN 補充:
Element:input 事件
HTML 元素:change 事件

當綁定了元素,v-model 會自動設置元素要對應到的「屬性、監聽事件」。
例如:綁定了 textareav-model 就知道要幫我們綁上 value 屬性,並監聽 input 事件。

接下來讓我們看看這些表單輸入綁定的範例吧!

input text 範例

  1. v-modeltext 綁定到輸入框,監聽 input 事件。
  2. 定義 text 的初始值,設為響應式狀態的空字串。
  3. 使用者寫入內容後,input 事件觸發,inputvalue 被傳到 text 中。
  4. text 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const text = ref("");
</script>
<template>
  <h3>input text</h3>
  <input v-model="text" />
  <p>你輸入的內容是:{{ text }}</p>
</template>

textarea 範例

  1. v-modeltextarea 綁定到輸入框,監聽 input 事件。
  2. 定義 textarea 的初始值,設為響應式狀態的空字串。
  3. 使用者寫入內容後,input 事件觸發,inputvalue 被傳到 textarea 中。
  4. textarea 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const textarea = ref("");
</script>
<template>
  <h3>textarea</h3>
  <textarea v-model="textarea" placeholder="請輸入一些內容..." />
  <p>你輸入的內容是:{{ textarea }}</p>
</template>

textarea 不支持插值表達式

注意以下語法是無效的喔。

<textarea>{{ someText }}</textarea> <!-- 無效 -->

checkbox 範例

單選 checkbox

  1. v-modelisCheckedSingle 綁定到輸入框,監聽 change 事件。
  2. 定義 isCheckedSingle 的初始值,設為響應式狀態的 false
  3. 使用者選擇選項後,change 事件觸發,inputvalue 被傳到 isCheckedSingle 中。
  4. isCheckedSingle 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const isCheckedSingle = ref(false);
</script>
<template>
  <div>
    <h3>單選 checkbox</h3>
    <input type="checkbox" id="checkbox" v-model="isCheckedSingle" />
    <label for="checkbox">點選選項</label>
    <p>是否選取? {{ isCheckedSingle }}</p>
  </div>
</template>

多選 checkbox

  1. v-modelisCheckedMultiple 綁定到輸入框,監聽 change 事件。
  2. 定義 isCheckedMultiple 的初始值,設為響應式狀態的「空陣列」。
  3. 使用者選擇選項後,change 事件觸發,inputvalue 被傳到 isCheckedMultiple 中。
  4. isCheckedMultiple 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const isCheckedMultiple = ref([]);
</script>
<template>
  <div>
    <h3>多選 checkbox</h3>
    <input type="checkbox" id="Jami" value="Jami" v-model="isCheckedMultiple" />
    <label for="Jami">Jami</label>
    <input
      type="checkbox"
      id="Irene"
      value="Irene"
      v-model="isCheckedMultiple"
    />
    <label for="Irene">Irene</label>
    <input
      type="checkbox"
      id="Jenny"
      value="Jenny"
      v-model="isCheckedMultiple"
    />
    <label for="Jenny">Jenny</label>
    <p>你選擇的選項是:{{ isCheckedMultiple.join() }}</p>
  </div>
</template>

radio 範例

  1. v-modelselectedOption 綁定到輸入框,監聽 change 事件。
  2. 定義 selectedOption 的初始值,設為響應式狀態的「空字串」。
  3. 使用者選擇選項後,change 事件觸發,inputvalue 被傳到 selectedOption 中。
  4. selectedOption 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const selectedOption = ref("");
</script>
<template>
  <div>
    <label>
      <input type="radio" value="選項一" v-model="selectedOption" />
      選項一
    </label>
    <label>
      <input type="radio" value="選項二" v-model="selectedOption" />
      選項二
    </label>
    <p>你選擇的選項是:{{ selectedOption }}</p>
  </div>
</template>

select 範例

單選範例

  1. v-modelisSelected 綁定到輸入框,監聽 change 事件。
  2. 定義 isSelected 的初始值,設為響應式狀態的「空字串」。
  3. 使用者選擇選項後,change 事件觸發,inputvalue 被傳到 isSelected 中。
  4. isSelected 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const isSelected = ref("");
</script>

<template>
  <div>
    <h3>select</h3>
    <select v-model="isSelected">
      <option value="" disabled>請選擇</option>
      <option value="選項一">選項一</option>
      <option value="選項二">選項二</option>
      <option value="選項三">選項三</option>
    </select>
    <p>Select 當前狀態:{{ isSelected }}</p>
  </div>
</template>

注意:預設選項的如果都不是任何其他選項,為了確保用戶體驗,官方建議設置一個預設的選項,並設置 value=""disabled 屬性。
這樣可以避免用戶在選擇時出現問題,確保能夠正確觸發 change 事件。

多選範例

  1. v-modelisSelectedMultiple 綁定到輸入框,監聽 change 事件。
  2. 定義 isSelectedMultiple 的初始值,設為響應式狀態的空字串。
  3. 使用者選擇選項後,change 事件觸發,inputvalue 被傳到 isSelectedMultiple 中。
  4. isSelectedMultiple 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const isSelectedMultiple = ref([]);
</script>

<template>
  <div>
    <h3>select multiple</h3>
    <select v-model="isSelectedMultiple" multiple>
      <option value="選項一">選項一</option>
      <option value="選項二">選項二</option>
      <option value="選項三">選項三</option>
    </select>
    <p>Select 當前狀態:{{ isSelectedMultiple }}</p>
  </div>
</template>

option 用 v-for 渲染

  1. v-modelisSelectedVFor 綁定到輸入框,監聽 change 事件。
  2. 定義 isSelectedVFor 的初始值,設為響應式狀態的「ㄧ」文字。
  3. 使用者選擇選項後,change 事件觸發,inputvalue 被傳到 isSelectedVFor 中。
  4. isSelectedVFor 的內容即時渲染到模板上。
<script setup>
import { ref } from "vue";

const isSelectedVFor = ref(`ㄧ`);
const options = [
  { title: `選項一`, value: `一` },
  { title: `選項二`, value: `二` },
  { title: `選項三`, value: `三` },
];
</script>
<template>
  <div>
    <h3>select v-for</h3>
    <select v-model="isSelectedVFor">
      <option value="" disabled>請選擇</option>
      <option v-for="option in options" :value="option.value">
        {{ option.title }}
      </option>
    </select>
    <p>選項{{ isSelectedVFor }}</p>
  </div>
</template>

我要複習 v-for

v-bind 值綁定

通常 checkboxradioselectv-model 上綁定的值都是單一靜態字串(單選 selectboolean 值),但若我們想要讓其綁定動態數據,可以用 v-bind 綁定表達式,讓屬性綁定為自定義的動態值。

官方文件:但有時我們可能希望將該值綁定到當前組件實例上的動態數據。這可以通過使用 v-bind 來實現。此外,使用 v-bind 還使我們可以將選項值綁定為非字符串的數據類型。

直接來看看在使用上的範例吧~

checkbox

基礎綁定

<input
  type="checkbox"
  v-model="綁定的數據"
  true-value="yes"
  false-value="no" />

確保值的提交

true-valuefalse-value 是 Vue 在 v-model 中的特殊屬性,用來定義 checkbox 勾選/未勾選時的 value,在這,綁定的數據會在:

  • 勾選時設置為 yes
  • 未勾選時設置為 no

這兩個值可以確保:無論使用者的選擇是什麼,都有值可以提交,因為使用者的選擇,對於表單提交功能來說是很重要的!
但官方文件提到:如果不想設置這兩個屬性的話,建議使用 radioradio 是單選,確保了每個選項都會寫入值。

自定義的動態綁定

<input
  type="checkbox"
  v-model="綁定的數據"
  :true-value="自定義的true動態值的表達式"
  :false-value="自定義的false動態值的表達式" />

我們以一個範例來看預設值/自定義值的差別~

<script setup>
import { ref } from "vue";

const isChecked = ref("");
const isCheckedCustom = ref("");
const customTrueValue = ref("自定義的true動態值");
const customFalseValue = ref("自定義的false動態值");
</script>

<template>
  <div>
    <h3>單選 checkbox toggle yes/no</h3>
    <input
      type="checkbox"
      id="checkbox"
      v-model="isChecked"
      true-value="yes"
      false-value="no"
    />
    <label for="checkbox">點選選項</label>
    <p>是否選取? {{ isChecked }}</p>
  </div>
  <div>
    <h3>單選 checkbox toggle 自定義的動態值</h3>
    <input
      type="checkbox"
      id="isCheckedCustom"
      v-model="isCheckedCustom"
      :true-value="customTrueValue"
      :false-value="customFalseValue"
    />
    <label for="isCheckedCustom">點選選項</label>
    <p>是否選取? {{ isCheckedCustom }}</p>
  </div>
</template>

radio

自定義的動態綁定

<input type="radio" v-model="綁定的數據" :value="自定義的表達式" />你的第一個選項
<input type="radio" v-model="綁定的數據" :value="自定義的表達式" />你的第二個選項

我們可以這樣設定:

<script setup>
import { ref } from "vue";

const selectedOption = ref("");
const selectedFirstValue = ref("自定義的選項一的值");
const selectedSecondValue = ref("自定義的選項二的值");
</script>
<template>
  <div>
    <h3>radio</h3>
    <label>
      <input
        type="radio"
        v-model="selectedOption"
        :value="selectedFirstValue"
      />
      選項一
    </label>
    <label>
      <input
        type="radio"
        v-model="selectedOption"
        :value="selectedSecondValue"
      />
      選項二
    </label>
    <p>你選擇的選項是:{{ selectedOption }}</p>
  </div>
</template>

select

自定義的動態綁定

也可以綁定非字串的值。

這邊以 {} 作為範例。

<select v-model="綁定的數據">
  <option :value="{ 物件屬性: 物件 value }"></option>
</select>

上範例:

<script setup>
import { ref } from "vue";

const isSelected = ref("");
</script>

<template>
  <div>
    <h3>select</h3>
    <select v-model="isSelected">
      <option :value="" disabled>請選擇</option>
      <option :value="{ option: 1 }">選項一</option>
      <option :value="{ option: 2 }">選項二</option>
      <option :value="{ option: 3 }">選項三</option>
    </select>
    <p>Select 當前狀態:{{ isSelected }}</p>
  </div>
</template>

修飾符

lazy

v-model 的預設行為會是 input 事件後更新數據,lazy 可使它更改為在 change 事件後更新數據。

<input v-model.lazy="綁定的數據" />

number

預設將使用者輸入框內容轉為數字,如果該值無法被 parseFloat() 處理,會 return 原始的值。

<input v-model.number="綁定的數據" />

trim

預設自動去除使用者輸入框內容兩端的空格。

<input v-model.trim="綁定的數據" />

小結

這種操作方式真的直觀多了,超讚的 QQ

跟著官網的列表順序看文件,list 不知不覺往下往下再往下,本菜感覺 Vue 已經準備要帶我進入到另一個的異世界去了,但如 Day1 說的!!!士氣必須得繼續の高昂下去,誰怕誰的樣子要先裝出來。

OK 明天準備撞進「生命週期」(對沒有錯就是那張圖)
/images/emoticon/emoticon78.gif
/images/emoticon/emoticon78.gif

範例 code ⬇️

https://github.com/Jamixcs/2024iThome-jamixcs/tree/main/src/components/day23

參考資料


上一篇
欸你是要進 Vue 了沒? - Day22:Vue 事件處理之 v-on @我知道你什麼事都聽到了
下一篇
欸你是要進 Vue 了沒? - Day24:Vue 生命週期之從組件來到了這世界到它完成任務後離開的過程
系列文
欸你是要進 Vue 了沒?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言