為了多一點 Vue 的實戰練習,經網路推薦宅幹嘛 Vue 系列,透過 Alex 幽默又生活化的講述,覺得讓這個框架又顯得易學很多,這次就跟著宅幹嘛在 2018 年 IT 鐵人賽 Vue.js 手牽手,一起嗑光全家桶來做一系列的練習。
學習重點
畫面結構
上方圖片可以看到畫面有幾樣資訊:
- 頁面圖片。
- 頁面標題。
- 選擇箭頭按鈕。
- 排序編號、項目名稱、選單標題。
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
| <div id="app"> <div class="container"> <img src="https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80" /> <h1>Practice Vue With Alex</h1> </div>
<div class="container"> <div class="option"> <a href="#"> <i class="fas fa-caret-left fa-3x"></i> </a> <div class="optionTitle"> <span class="number">1</span> <span class="type">練習一</span> <span class="title">選單事件綁定</span> <a href="#"></a> </div> <a href="#"> <i class="fas fa-caret-right fa-3x"></i> </a> </div> </div> </div>
|
資料區
下方為準備的資料區域:
- title: 預備好的標題字串。
- src: 圖片。
- data: 選單內容,有類型、標題、連結。
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 44 45 46 47 48 49 50 51 52 53
| let data = { title: "Practice Vue With Alex", src: "https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80", index: 0, menu: [ { type: "練習一", title: "選單事件綁定", link: "#", }, { type: "練習二", title: "雙向資料表單處理", link: "#", }, { type: "練習三", title: "使用者輸入呈現", link: "#", }, { type: "練習四", title: "篩選資料轉換", link: "#", }, { type: "練習五", title: "互動式資料選單", link: "#", }, { type: "練習六", title: "CSS + jQuery 動畫", link: "#", }, { type: "練習七", title: "資料觀測與設定", link: "#", }, { type: "練習八", title: "家鄉通訊錄 API", link: "#", }, { type: "練習九", title: "TodoList 實做", link: "#", }, ], };
|
雙向綁定做出標題與圖片
- 就用雙括號將標題的字串用
Vue 全家桶系列 - 古早味事件燉畫面綁定
帶入 templete 中。
- 使用屬性綁定圖片
:src="src"
。即完成綁定,等等加上 Vue 實體就會正確顯示在畫面上。
1 2 3 4
| <div class="container"> <img :src="src" /> <h1>{{title}}</h1> </div>
|
資料起始點設定
因為目前資料中有十筆資料,但正常來說畫面顯示應該只有一筆,所以在資料中的起始點多給一個屬性 index
,其值為 0
,代表我一開始要從第一筆顯示。
1 2 3 4 5 6 7 8 9
| let data = { title: "Practice Vue With Alex", src: "https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80", index: 0, menu: [ ...資料部分略... ], };
|
用 Vue 把畫面與資料連起來
有畫面也有資料了,中間的媒介就是 Vue 了,如果用這樣就更好理解。
再來就是建立 Vue 的實體,並把畫面與資料先建立好。
Vue
1 2 3 4
| let vm=new Vue({ el: "#app", data: data, })
|
把剩下的畫面的資料也綁好,如下:
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div class="option"> <a href="#"> <i class="fas fa-caret-left fa-3x"></i> </a> <div class="optionTitle"> <span class="number">{{index+1 }}</span> <span class="type">{{menu[index].type}}</span> <span class="title">{{menu[index].title}}</span> <a :href="menu[index].link"></a> </div> <a href="#"> <i class="fas fa-caret-right fa-3x"></i> </a> </div>
|
點擊事件
在要點擊的按鈕上加 v-on
事件,並且給予對應的 methods
,其事件名稱為 changePage()
,因為會有往前跟往後,所以參數就給予 -1
與 1
,
html
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <div class="option"> <a href="#" @click.prevent="changePage(-1)"> <i class="fas fa-caret-left fa-3x"></i> </a> <div class="optionTitle"> <span class="number">{{index+1 }}</span> <span class="type">{{menu[index].type}}</span> <span class="title">{{menu[index].title}}</span> <a :href="menu[index].link"></a> </div> <a href="#" @click.prevent="changePage(1)"> <i class="fas fa-caret-right fa-3x"></i> </a> </div>
|
vue
因為在前面事件有帶入參數,所以在方法中也給予一個對應的參數名稱,其名稱可自訂。
- Vue 的 index 做加總。
this 在 vue 中已被包裝指向 vue 本身,所以不會在指到 window 物件。
- 判斷,如果此 index 小於 0 ,則 index 就為第一筆。
- 或是此 index 大於 9,則此 index 就會是 9。因為陣列排序從 0 開始,所以資料長度要 -1。簡單說就是自己等於自己。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var vm = new Vue({ el: "#app", data: data, methods: { changePage(change) { this.index += change; if (this.index < 0) { this.index = 0; } else if (this.index > menu.length - 1) { this.index = change - 1; } }, }, });
|
但有趣的可以使用餘數的觀念,就會變成下方寫法。
1
| this.index = (this.index + change + this.menu.length) % this.menu.length;
|
什麼是餘數
這是一個很不錯的技巧,數學極爛的我真是覺得小時候應該多熟悉點基本數學觀念,但餘數這個還可以,舉例:
20 / 3=18
餘 2
39/5=7
餘 4
,
這是國小除法應該會教到,那這有什麼關係,以上兩個規則會發現,
3 的餘數為 0、1、2。
5 的餘數為 0、1、2、3、4。
由此可知,陣列的數量與餘數的數量相同,如果把數字帶入下方公式就會很明顯得到結果。
目前資料有 10 筆資料,所以:
this.index
= 0
, 陣列起始為 0
。
change
= 1
or -1
,
this.menu.length
= 10
。
1
| this.index = (this.index + change + this.menu.length) % this.menu.length;
|
但這邊為什麼要加上 this.menu.length
呢? 如果不帶陣列長度的話會變這樣:
加號的話,(0 +1) %10
會餘 1
,加號沒什問題。
但如果是帶 -1
的時候會變 (0 -1 )%10
,餘數會變 -1
,然後就壞掉了。
所以加上陣列長度是確保加總值會維持為真值,也就是正值,就不會壞掉了。
加號:(0 +1+10) %10
餘 1
。
減號:(0 -1+10) %10
餘 9
。
這招好強啊!!
是用於圖片輪播或是循環選單,而且可以一行抵六行,更簡潔的寫法!
寫到這邊基本上功能都已經完成且可以正常運作。
優化程式碼
為了讓程式碼更好閱讀,可以把重複出現的程式碼使用 computed 屬性統一整理,就把剛剛重複出現的兩個程式碼整理好,
computed
1 2 3 4 5 6 7 8 9
| computed: { today() { return this.menu[this.index]; }, total() { return this.menu.length; }, },
|
最後再把該 this.menu[this.index]
跟 this.menu.length
替換成這兩個方法即可。
當第一跟最後的隱藏箭頭圖示
為了讓使用者更合理使用介面,當資料選到第一項與最後一項的時候,要隱藏左邊跟右邊的箭頭。
這時使用 v-if
判斷箭頭的條件。
左邊箭頭
1 2 3 4 5
|
<a v-if="index > 0" href="#" @click.prevent="changePage(-1) "> <i class="fas fa-caret-left fa-3x"></i> </a>
|
右邊箭頭
1 2 3 4 5
|
<a v-if="index < total -1" href="#" @click.prevent="changePage(1)"> <i class="fas fa-caret-right fa-3x"></i> </a>
|
這樣在選到第一個跟最後一個的時候,就會隱藏起頭與最後的箭頭了!
最後程式碼可以看 CodePen
參考資料
開胃餐點 - 古早味事件燉畫面綁定