本篇主要是透過線上課程:HiSKIO
、官方文件及網路上搜尋資源所學習的。
表單綁定 Event handling
text input &textarea
在 input 的 v-model 其實就是 v-bind:value 加上偵聽 input 事件 v-on:input。
textarea 中則是可以多行輸入,但 html 上顯示一般來說一樣是單行顯示,如果要在 html 上保留原本的換行字元。將綁定元素的標籤改為pre
,preserve 即可,或者在 css 中用white-space: pre;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <style> h1 { white-space: pre; } </style>
<div id="app"> <input type="text" v-model="msg" /> <input type="text" :value="msg" @input="setMessage" /> <h1>{{msg}}</h1> <textarea v-model="message"></textarea> <pre>{{message}}</pre> <h1>{{message}}</h1> </div>
<script> new Vue({ el: "#app", data: { msg: "", message: "" }, methods: { setMessage(evt) { console.log(evt); this.msg = evt.target.value; } } }); </script>
|
checkbox
checkbox 可以單選綁定,也可以多選綁定。
單選-確認選擇 agree 後,submit 才會成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <div id="app"> <input type="checkbox" id="check" v-model="agree" /> <label for="check">Agree</label> <h1>{{agree}}</h1> <button @click="submit">Submit</button> </div>
<script> new Vue({ el: "#app", data: { agree: false }, methods: { submit() { if (this.agree !== true) { alert("Please agree!"); return; } } } }); </script>
|
多選-v-model 綁定相同名稱,該名稱宣告為陣列,但順序是依照勾選的順序來呈現。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <div id="app"> <input type="checkbox" id="check1" value="morning" v-model="times" /> <label for="check1">Morning</label> <input type="checkbox" id="check2" value="afternoon" v-model="times" /> <label for="check2">Afternoon</label> <input type="checkbox" id="check3" value="evening" v-model="times" /> <label for="check3">Evening</label> <h1>{{times}}</h1> </div>
<script> new Vue({ el: "#app", data: { times: [] } }); </script>
|
radio
透過 v-model 綁定相同的名稱,來達成單選,技術上可以達成多選,但不建議,要多選建議用 checkbox。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <div id="app"> <input type="radio" id="r1" v-model="gender" value="male" /> <label for="r1">Male</label> <input type="radio" id="r2" v-model="gender" value="female" /> <label for="r2">Female</label> <h1>{{gender}}</h1> </div> <script> new Vue({ el: "#app", data: { gender: "male" } }); </script>
|
select & option
下拉選單綁定
單選
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <div id="app"> <select v-model="year"> <option disabled value="">Select Year</option> <option>2015</option> <option value="16">2016</option> <option value="17">2017</option> </select> <h1>{{year}}</h1> </div>
<script> new Vue({ el: "#app", data: { year: "" } }); </script>
|
多選,用 multiple,綁定陣列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <div id="app"> <select v-model="years" multiple> <option disabled value="">Select Year</option> <option>2015</option> <option value="16">2016</option> <option value="17">2017</option> </select> <h1>{{years}}</h1> </div>
<script> new Vue({ el: "#app", data: { years: [] } }); </script>
|
不把每一個 option 打出來時,用 v-for
- data 中宣告陣列,宣告一開始 v-model 預設數值
- v-for 中的陣列用數字帶入,data 中不需樣宣告陣列
- data 中宣告的陣列每一個都為物件,value 與 text 分別取用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <div id="app"> <select v-model="selectedYear"> <option v-for="year in years" :value="year">{{year}}</option> </select> <h1>{{selectedYear}}</h1>
<select v-model="selectedMonth"> <option v-for="month in 12" :value="month">{{month}}</option> </select> <h1>{{selectedMonth}}</h1>
<select v-model="selectedGender"> <option v-for="option in options" :value="option.value" >{{option.text}}</option > </select> <h1>{{selectedGender}}</h1> </div>
<script> new Vue({ el: "#app", data: { years: [2015, 2016, 2017], selectedYear: 2015,
selectedMonth: 1,
options: [ { value: 1, text: "Male" }, { value: 2, text: "Female" }, { value: 3, text: "Others" } ], selectedGender: 1 } }); </script>
|
檔案上傳與圖片預覽
檔案上傳的圖片預覽,input type=”file” 綁定 v-model 是沒有用的,需要綁定 chagne 事件偵聽。
如果 type 是 file,事件觸發傳入的 event 裡面的 target 會有 files,是以 file list 呈現。
之後再 new 一個fileReader()
,針對這個 reader 偵聽 load 事件,並用 readAsDataURL 轉為 data:URL(base64 編碼),偵聽 load 事件後執行的函式,則是把事件參數的 evt.traget.result 指回到 vue data 中的 image。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <div id="app"> <input type="file" @change="fileSelected" /> <br /> <img v-if="image" :src="image" width="200" /> <br /> <button @click="upload">Upload</button> </div>
<script> new Vue({ el: "#app", data: { image: "", file: null }, methods: { fileSelected(evt) { this.file = evt.target.files.item(0); const reader = new FileReader(); reader.addEventListener("load", this.imageloaded); reader.readAsDataURL(this.file); }, imageloaded(evt) { console.log(evt); this.image = evt.target.result; } } }); </script>
|
檔案上傳的方式不一定,基本上是後端而定。
偵聽點擊 upload 事件
1 2 3 4 5 6 7 8 9 10 11 12
| upload() { axios.post('/upload', { image: this.imgage });
const form = new FormData(); form.append(this.file, this.file.name); axios.post('/upload', form); },
|
語法糖修飾符 modifier
- lazy: blur 離開焦點的時候才會觸發綁定
- number: 輸入的值當成一個數字,原本是字串
- trim: 輸入的值前後的空格裁掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <div id="app"> <input type="text" v-model.lazy="msg" /> <h1>{{msg}}</h1>
<input type="text" v-model.number="num" /> <h1>{{num+1}}</h1>
<input type="text" v-model.trim="text" /> <h1>[{{text}}]</h1> </div>
<script> new Vue({ el: "#app", data: { msg: "", num: 0, text: "" } }); </script>
|