Vue.js — Form各種表單與data的綁定. Vue關於資料的綁定，先前曾經提過使用{{…
By: Sean Yeh
Tags: JavaScript, Vuejs, Javascript Frameworks, Vue

另外，我們來看看一個非標準的選項。

Pills

這種輸入方式是，在使用者輸入關鍵字並且在關鍵字後面打上逗號之後，逗號前面的資料就會成為一個項目輸入資料裡面。

雖然這不算是form表單裡面標準的欄位，但近來這種輸入方式已經蠻流行的。

我們試著在這個專案中建立一個。在這裡可以將它用在輸入「負責專案」的資料。

在以專案為主的工作中，一位使用者可能同時負責了多項專案，需要輸入多的項目。因此，可以透過pill的輸入方式來搜集這樣的資料。pill的外觀上看起來不一樣，實際上使用到的還是input欄位。於是先建立一個 <input> 。

在這input裏，使用者可以一次一個關鍵字的依序的輸入不同的專案名稱（或關鍵字）。我們希望這些輸入的名稱或關鍵字最後會被收錄在一個資料屬性裡面。

在所有資料尚未搜集完全之前，我們需要一個暫時儲存的地方，因此透過 v-model 綁定 tempProjects ，作為暫時儲存資料的地方。

<label for="projects">負責專案</label>

<input id="projects" type="text" v-model="tempProjects">

同時在data裡面設定一個tempProjects來接收輸入的暫時資料。

另外，data裡面再設定一個projects來接收所有被整理過的暫時的結果。這個projects為陣列。也就是把一項項暫時資料合併為一個array，放入projects裡面。projects存放的才是「負責專案」的最終資料。

export default { data() {

return {

...略...

tempProjects:"",

projects:[]

};

}, };

鍵盤事件 keyboard event

有時候我們需要使用到鍵盤事件。例如希望使用者在input中「輸入」關鍵字並且緊接在後面「打上」逗號之後，逗號前面的資料就會成為一個項目輸入資料裡面。

拆解前面的過程，可以分為兩個動作：一個是輸入input、另一個是打上逗號之後離開input。這兩個動作完全沒有透過滑鼠點擊，只用了鍵盤來實現。因此我們需要監聽鍵盤的事件。

監聽鍵盤事件的方式有keypress、keydown、keyup等等。我們在這裏使用了keyup事件：鍵盤按下之後放開會觸發的事件。亦即當使用者「下好離手」時，就會觸發監聽事件，並且執行addProject。

<input id="projects" type="text" v-model="tempProjects" @keyup="addProject">

基於此，我們還需要在methods裡面增加一個addProject函式如下。這個函式需要帶入event（或e）做為參數。

methods: { addProject(e) {

console.log(e);

}, },

使用console來看看會有什麼結果。可以發現，只要按一下鍵盤上的任何按鍵，event事件就會被偵測到。這當然也包含了「打上逗號」這個事件。在console中可以看到，輸入逗號時，會得到 key: “,” 。

我們接下來，就是要監聽這個事件。

因此，可以將上面的函式改寫如下：

methods: { addProject(e) {

if (e.key === "," && this.tempProjects) { // do something.... }

},

},

這裡使用兩種條件來判斷是否執行這個函式， && 符號的左邊與右邊都必須符合條件（true），整體才符合條件（true）。

兩種條件中的第一個，是依照使用者是否在鍵盤中輸入「逗號」（ e.key === “,” ）的鍵盤事件，作為判斷基礎。另一個條件是，逗號前面必須有輸入值（ this.tempProjects ），我們不希望內容放著空白，只因為輸入逗號就成為一個項目。因此在這裡加上 this.tempProjects 來判斷這個值是否存在（ 因為 v-model=”tempProjects” ）。

一但符合這兩種條件條件後，就可以把tempProjects取得的資料，透過push集中收錄projects裡面。

this.projects.push(this.tempProjects);

資料收錄完畢之後，將tempProjects重新指定為空，以清除input欄位殘存的文字，等待使用者再次輸入資料。

this.tempProjects = "";

截至目前為止，methods裡面的addProject函式程式碼應該為下面。

methods: { addProject(e) {

if (e.key === "," && this.tempProjects) {

this.projects.push(this.tempProjects);

this.tempProjects = "";

}

}, },

接下來，需要將整合的projects資料顯示在畫面上讓使用者可以看到。透過v-for，將結果依序循環的放在下面的地方：

<div v-for="project in projects" :key="project">{{project}}</div>

如畫面，逐一輸入文字並且加上逗號後，可以出現一組組的內容：

功能優化

到目前為止pill的功能似乎已經完成大半。不過，你會發現至少還有三個問題：

第一，在每個pill的字串中，都有一個「逗號」。逗號是我們啟動事件的一個提示符號，我們並不希望將這個符號收錄到每個字串資料裡面。

第二個問題，依照現在的功能，我們可以重複輸入一模一樣的字串，若不修正這個問題，就會導致日後產生很多重複的pill。這也是這個功能所不希望發生的。

最後，我們希望在編輯的過程中點擊已經加入的pill字串，可以直接刪除該項pill。接下來，將針對這三項來優化程式碼。

優化1：避免重複的輸入

首先，要避免重複的輸入。實際的作法上，可以透過判斷該次輸入的資料（tempProjects）是否與已經存在於projects裡面。易言之，就是放在暫存位置 tempProjects 的資料是否包含在 projects 陣列之中？我們可以將這個問題寫成下面的if 判斷式。

if(this.projects.includes(this.tempProjects)){ // do something... }

若判斷的結果不為真（false），才把tempProjects資料加入projects陣列裡面，反之，則不可以加入projects裡面。因此原來的程式碼就需要改為：

methods: { addProject(e) {

if (e.key === "," && this.tempProjects) {

if (!this.projects.includes(this.tempProjects)) {

// do something...

this.projects.push(this.tempProjects);

}

this.tempProjects = "";

}

}, },

也就是要在push之前，必須先進行這個條件的判斷。

優化2：逗號的問題

接著要處理逗號的問題。在此採用系統修飾鍵ctrl。亦即當使用者同時輸入「ctrl+ 逗號」時，才會觸發事件。

@keyup.ctrl="addProject"

因此需要在 @keyup 後面加上 ctrl ，這樣子就可以成功的排除「逗點」，讓它不會再出現。

優化3：點擊pill刪除

最後要增加刪除pill功能：點擊pill就可以刪除該pill的功能。

因此，我們需要在pill上面增加一個 click事件，這個事件取名為deleteProject，並且需要帶入參數。在這裡帶入project當作參數。

<div v-for="project in projects" :key="project"> <span @click="deleteProject(project)">{{ project }}</span> </div>

在methods裡面也需要增加一個deleteProject函式對應。

deleteProject(project){ // do something... }

我們透過javascript的filter來filter掉projects陣列中的元素，把資料從projects陣列中刪除。

filter() 會回傳一個陣列array，其條件是返回 return 後方為真『 true』 的物件。也就是要返回 project !== item 的物件。

deleteProject(project){ this.projects = this.projects.filter(function(item){

return project !== item

}) }

如此就可以透過點擊pill，刪除不要的項目。

Submit確認送出

表單製作的最後一個步驟，就是要把表單送出。一旦使用者按下送出按鈕，表單會檢查輸入的內容，並且送出通過檢查的資料。submit按鈕就是用來送出表單。

因此要在form標籤的最後（一般來說會放在 </form> 之前）增加一組submit按鈕。

<form> ...略... <button>建立帳號</button> </form>

增加完submit按鈕後，還要在form標籤（前半段 <form> 標籤）上面加上一個 @submit （v-on:submit），並且給定一個方法（這裡為handleSubmit方法）。另外，在 v-on:submit 後面加入prevent可以避免每次點擊submit，就重新整理畫面的問題。

<form @submit.prevent="handleSubmit">

在methods裡面，同時增加一個handleSubmit方法。

handleSubmit() { console.log("帳號建立！！！");

console.log("email", this.email);

console.log("密碼", this.password);

console.log("角色", this.role);

console.log("負責專案", this.projects);

console.log("興趣", this.fun);

console.log("閱讀並同意", this.terms); }

結論

透過v-model的使用，將資料進行雙向的綁定，可以讓Form表單介面在使用上更加的流暢。另外，由於我們在這裡沒有使用到任何儲存資料的資料庫，於是在這個函式裡面僅將資料透過console的方式顯示出來。日後有機會，可以將這個部分與MySQL或Firebase等資料庫串接後，透過修改handleSubmit方法，把資料傳送到資料庫裡面。