整個系列都快要完結篇了,怎麼可能獨漏 Vue 的神奇語法糖—— v-model
呢?我們已經知道 Vue 基於 MVVM 架構模式,最大的特色就是可以將資料與畫面進行雙向綁定並同步更新,而 v-model
正是運用在表單元素如 <input>、<textarea>、<select> 的神奇連動語法,使用之前先來了解一下概念與規則:
需在元件內的 data 聲明初始值:v-model
會忽略表單元素的初始值如 value、checked 等,因此需在 data 聲明初始值作為 v-model
的綁定值
data() {
return {
inputText: "",
};
},
一般在元件內的 <input> 使用 v-model
<pre>@input 即時顯示輸入內容:{{ inputText }}</pre>
<label>搜尋:
<input type="text" v-model="inputText" />
</label>
相當於 v-model
= v-on:input
+ v-bind:value
:監聽表單元素的即時變化
<input type="text" :value="inputText" @input="value = $event.target.value" />
結尾加上修飾符的 v-model.lazy
<pre>@change 失去聚焦後才確認輸入內容:{{ inputText }}</pre>
<label>搜尋:
<input type="text" v-model.lazy="inputText" />
</label>
相當於 v-model
= v-on:change
+ v-bind:value
:監聽表單元素失去聚焦後的變化
<input type="text" :value="inputText" @change="value = $event.target.value" />
v-model
以我們現有在 BookList.vue 中的搜尋欄位為例,原本在 Day 23 中示範將事件從子元件 $emit
拋給父元件處理:
<!-- 子元件 -->
<label>搜尋書本:
<input
type="text"
:value="inputText"
@input="$emit('searchBook', $event)"
/>
</label>
<!-- 父元件 -->
<BookList
navTitle="All"
:bookList="books"
:inputText="searchText"
@searchBook="searchText = $event.target.value"
/>
若改為在父元件使用 v-model
,則需將子元件的 $emit
事件名稱修改為原始的 input 事件,綁定值也是原始的 value
,以供父元件透過 v-model
監聽 input 事件,再將監聽結果更新到 value
,再 prop 給子元素渲染出結果。
<!-- 子元件 -->
<label>搜尋書本:
<input
type="text"
:value="value"
@input="$emit('input', $event.target.value)"
/>
</label>
<!-- 父元件 -->
<BookList
navTitle="All"
:bookList="books"
v-model="searchText"
/>
update:myPropName
v-model
使用起來確實很方便,但每個人對於語法的掌握度和使用上的熟練程度不同,都會影響偏好的方式;若是習慣拆分成 v-on
和 v-bind
使用上也相對靈活,方便處理細部的調整,個別對事件和資料進行設定的主控性相對較高。
至於 v-on
和 v-bind
的管理,Vue 也有推薦可以使用 update:myPropName
模式為事件命名,這樣便能讓事件名稱和 prop 相互呼應,在元件中使用也可以一目了然兩者之間的關聯性。
<!-- 子元件 -->
<label>搜尋書本:
<input
type="text"
:value="keyword"
@input="$emit('update:keyword', $event)"
/>
</label>
<!-- 父元件 -->
<BookList
navTitle="All"
:bookList="books"
:keyword="searchText"
@update:keyword="searchText = $event.target.value"
/>