跳至主要内容

[Vue] Vue指令-雙向綁定

TL;DR

使用v-model會根據所定義的資料格式不同,以及所綁定的input不同有不一樣的效果。

相關連結


input

最基本的使用方式,輸入什麼,資料內的字串就會跟著變化

input(text)

<h3>input:text</h3>
<input type="text" class="form-control" v-model="name">
{{ name }}

input(number)

<h3>input:number</h3>
<input type="number" class="form-control" v-model="num">
{{ num }}

textarea

<h3>textarea</h3>
<textarea cols="30" rows="3" class="form-control" v-model="text"></textarea>
{{ text }}

checkbox

單選

單選的時候我們的資料格式會設定成布林值。選取會對應true不選取對應false

另外可以使用三元運算子調整渲染的文字內容,也可以在資料內給予初始預設值。

<h3>checkbox 單選框</h3>
<p>小明,你是吃飽沒?</p>
<p>{{ checkAnswer}}</p>
<p>{{ checkAnswer ? '吃飽了' : '還沒'}}</p>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="check1" v-model="checkAnswer">
<label class="form-check-label" for="check1">小明回覆</label>
</div>
另一種指定渲染內容的方法

前面使用三元運算子,可以將turefalse的值分別對應渲染出 "吃飽了""還沒"

還有另一種設定方式,可以達到一樣的效果:

vue
const App = {
data() {
return {
checkAnswer: true,
checkAnswer2: "小明還沒回覆",
checkAnswer3: [],
};
},
methods: {}
};

Vue.createApp(App).mount("#app");
html(#app)
<p>小明,你是吃飽沒?</p>
<p>{{ checkAnswer2 }}</p>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="check2"
v-model="checkAnswer2"
true-value="吃飽了"
false-value="還沒吃飽"
>
<label class="form-check-label" for="check2">小明回覆</label>
</div>

預設會顯示資料內的 “小明還沒回覆”,等到我們點選了按鈕,變成true的時候,就會改為顯示 吃飽了 ,再點一次變成false的時候會顯示 還沒吃飽

複選

要使用複選的checkbox的時候,v-model所綁定的資料需要是一個陣列。會分別將checked的按鈕對應的value給push到綁定的資料陣列中。

value

需要注意,這邊所傳入陣列的資料是value的值。

預設勾選

我們可以在資料的陣列內,直接加入希望預設勾選的checkboxvalue。則對應的選項就會被預設勾選。 如我們直接設定checkAnswer3:["蘿蔔糕","豆漿"],則蘿蔔糕跟豆漿都會被預設勾選。

但是如果今天在input內設定為vale="蘿蔔糕3",則會因為找不到對應valuecheckbox,所以並不會如我們設想的預設勾選。

<h3>checkbox 複選框</h3>
<p>你還要吃什麼?</p>
<p>{{ checkAnswer3.join(' ') }}</p>
<p>{{ checkAnswer3 }}</p>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="check3" value="蛋餅" v-model="checkAnswer3">
<label class="form-check-label" for="check3">蛋餅</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="check4" value="蘿蔔糕" v-model="checkAnswer3">
<label class="form-check-label" for="check4">蘿蔔糕</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="check5" value="豆漿" v-model="checkAnswer3">
<label class="form-check-label" for="check5">豆漿</label>
</div>

radio

沒有使用框架的時候,如果我們想要組成一個 radio group ,則需要在每個radio上加上name屬性。

使用vue的時候,會根據我們在v-model所綁定的資料,框架會自動幫我們調整好變成一個群組。我們就可以專心在資料上的處理。

使用時需要將資料設定為字串,如果字串值有對應到radio的value,則該radio會為預設選取。

select

單選

disabled小技巧

有時候我們會希望在一開始顯示一個預設的提示選項(例如:說吧,你要吃什麼)。但是當使用者選擇完畢之後又不希望使用者可以選擇回預設提示選項,這時候就可以善用disabled功能來達成。

首先先在預設的選項上撰寫一個value,並且讓data內的值與這個value相同(可以為空字串)。這麼一來,就會預設顯示該選項。

另外,我們可以在這個選項上加上disabled,這樣一來當使用者點選其他選項後,就會因為這個disabled而無法選擇回我們的提示選項。

<h3>select 單選</h3>
<p>你還要吃什麼?</p>
<p>{{ selectAnswer }}</p>
<select class="form-select" v-model="selectAnswer">
<option :value="" disabled>說吧,你要吃什麼?</option>
<option v-for="item in products" :key="item.name" :value="item.name">{{item.name}} / {{item.price}} 元</option>
</select>

多選

<h3>select 多選</h3>
<p>你還要吃什麼?</p>
<p>{{selectAnswer2}}</p>
<select class="form-select" v-model="selectAnswer2" multiple>
<option selected disabled value="">說吧,你要吃什麼?</option>
<option :value="item.name" v-for="item in products" :key="item.name">
{{item.name}} / {{item.price}} 元
</option>
</select>
v-for

option可以使用v-for去迴圈渲染出所有選項,但是需要記得只要有使用到v-for就要補上一個唯一值的:key

因為option傳入資料中是對應value值的,所以我們這邊需要再額外加入:value,動態綁定每個item.namev-for渲染出來的選項中。

v-model修飾符

v-model另外提供了三種修飾符。加上修飾符之後運作會有微小的不同,以下依序介紹。

<div id="app">
<div class="p-5">
<h4 class="mt-3">沒有延遲</h4>
{{ withoutLazyMsg }}
<input type="text" class="form-control" v-model="withoutLazyMsg">
<h4 class="mt-3">延遲 Lazy</h4>
{{ lazyMsg }}
<input type="text" class="form-control" v-model.lazy="lazyMsg">
<hr>
<h4 class="mt-3">type=text的 純數值 Number</h4>
{{ numberMsg1 }} {{ typeof numberMsg1 }}
<input type="text" class="form-control" v-model.number="numberMsg1">
<!-- safari就算使用type=number依然可以輸入數字以外的內容...好雷啊~~ -->
<h4 class="mt-3">限制type=number的 純數值 Number</h4>
{{ numberMsg2 }} {{ typeof numberMsg2 }}
<input type="number" class="form-control" v-model="numberMsg2">
<h4 class="mt-3">修剪 Trim</h4>
這是一段{{ trimMsg }}緊黏的文字
<input type="text" class="form-control" v-model.trim="trimMsg">
</div>
</div>

v-model.lazy

加上.lazy之後,將input資料寫回綁定資料的時間點就會改為onchange。

e.g: v-model.lazy="lazyMsg"

v-model.number

平時的input,就算我們輸入的是純數字,但是存入data中其實仍然是字串型別。

如果我們希望可以確保資料內容一定要是數字型別,就可以使用.number修飾符。

e.g: v-model.number="numberMsg"

input type的差異

如果我們綁定v-model.number的input設定為type="text",則我們仍然可以輸入數字以外的內容。

分為兩種狀況:

  1. 第一個字元為數字:
    則只會將字串前方的數字給存入變數中,只要有一個非數字的內容,後續的內容都不會存入

  2. 第一個數字為非數字:
    則內容會正常存入,但.number修飾符無作用,資料儲存為字串型別。

如果要避免這種狀況,可以將input設定為type="number",這樣一來就可以限制使用者不能輸入數字以外的內容。

Safari地雷

Safari就算限制type="number"使用者仍然可以輸入數字以外的內容!!

自動啟用.number

官方文件有提到如果在input設定type="number"v-model.number會自動啟用。

也就是以下兩行是相等的:

<input type="number" class="form-control" v-model="numberMsg">
<input type="number" class="form-control" v-model.number="numberMsg">

v-model.trim

如果不希望存入使用者在內容前後所輸入的空白字元時,就可以使用.trim修飾符。可以避免儲存到空白字元所造成的錯誤。

e.g: v-model.trim="trimMsg"