前文
最近面試有一間公司要求使用Restcountries API使用CRUD前端Html串接API,有看我文章的夥伴應該知道我大多是研究後端或CI/CD相關技術,對於前端技術較少研究,這次我打算使用vue.js來完成此次需求.
需求如下
- 分頁
- 顯示國家相關資訊
- 排序效果
- 點選國家名稱進入Detail頁面
因為以上幾點都是CRUD相關操作,關於CRUD相關操作使用三大框架就很適合(所以我選擇使用Vue)
話不多說先給大家看看成品 RestcountriesSample
Source Code
要使用的API介紹
雖然官網對於API介紹雖少,但我相信只要有常串API的人應該可以很快猜出每個API作用.
而且我發現大部分API都可以用GET來請求.
只要用這兩個就可以完成我們的需求
Code解說與問題分析
一開始我在分析問題是要找尋合適的API後面經過塞選挑出上面兩個API.
接下來我就考慮把畫面用Table + 分頁方式呈現,而Detail Page利用Query String方式傳Country Name來看明細資料.
我用Pure前端串接API,所以我建立兩個Html頁面
- 一個是Master Page
- 一個是Detail Page
Master page
在Javascript code我主要介紹流程
主要在一開始頁面建立時去Load All 資料並把資料binding在rows
陣列物件
orderBy
方法,提供一個排序實現這邊可以讓Page呼叫時傳入要排的欄位名稱就可以不用HardCode(使用類似@click="orderBy('name'),ASC *= -1"
)傳入Name就可以對於Name來排序,提高程式碼可用性
因為API請求有時候會比較久,所以我這邊使用vue-loading-overlay來當Loading Page(有興趣的可以在查閱此連結的API)
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
| <div id="app"> <template> <div class="vld-parent"> <loading :active.sync="isLoading" :is-full-page="true"></loading> </div> </template> <div><b>Search Country Name:</b> <input type="text" v-model="countryName"></div> <div v-if="filteredRows.length === 0">No Data Display!!</div> <table v-if="filteredRows.length > 0" class="table table-condensed"> <thead> <tr> <th>國旗</th> <th @click="orderBy('name'),ASC *= -1">國家名稱 <span class="icon" :class="{'Reverse':ASC==1}"> <i class="fa fa-angle-up"></i> </span> </th> <th>2位國家代碼</th> <th>3位國家代碼</th> <th>母語名稱</th> <th>替代國家名稱</th> <th>國際電話區號</th> </tr> </thead> <tr v-for="item in filteredRows.slice(pageStart, pageStart + pageSize)"> <td><img v-bind:src=item.flag style='height:150px'></td> <td> <a target="_blank" :href="'./CountryModel.html?countryName=' + item.name"> {{ item.name }} </a> </td> <td>{{ item.alpha2Code }}</td> <td>{{ item.alpha3Code }}</td> <td>{{ item.nativeName }}</td> <td>{{ item.altSpellings[0] }}</td> <td>{{ item.callingCodes[0] }}</td> </tr> </table> <div class="pagination"> <ul> <li v-bind:class="{'disabled': (currPage === 1)}" @click.prevent="setPage(currPage-1)"><a href="#">Prev</a></li> <li v-for="n in totalPage" v-bind:class="{'active': (currPage === (n))}" @click.prevent="setPage(n)"><a href="#">{{n}}</a></li> <li v-bind:class="{'disabled': (currPage === totalPage || totalPage === 0)}" @click.prevent="setPage(currPage+1)"><a href="#">Next</a></li> </ul> </div> </div>
|
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 54 55 56 57
| var app = new Vue({ el: '#app', data: { rows: [], pageSize: 25, currPage: 1, countryName: '', ASC: 1, isLoading: true }, computed: { filteredRows: function () { var self = this; return self.rows.filter(x=> !self.countryName || x.name.search(self.countryName) != -1); }, pageStart: function () { return (this.currPage - 1) * this.pageSize; }, totalPage: function () { return Math.ceil(this.filteredRows.length / this.pageSize); } }, methods: { setPage: function (index) { if (index <= 0 || index > this.totalPage) { return; } this.currPage = index; }, orderBy: function (item) { var self = this; return self.rows.sort(function (obj1, obj2) { var obj1 = obj1[item] var obj2 = obj2[item]
if (obj1 === obj2) return 0; else if (obj1 > obj2) return self.ASC; else return self.ASC * -1; }); } }, created: function () { var self = this; $.get('https://restcountries.eu/rest/v2/all', function (data) { self.rows = data; self.isLoading = false; }); }, watch:{ countryName:function(newValue){ this.currPage = 1; } } });
|
Detail Page
Detail我使用FULL NAME來查找我要的國家明細
Detail Html畫面,我就不多說可以看原始碼
因為我在設計時想要使用QueryString來傳送CountryName,所以我利用URLSearchParams
來取得QueryString countryName
資料並使用Ajax查詢API
如果查不到資料或使用者傳送一個不存在的資訊,我就會顯示No Data Display!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| var app = new Vue({ el: '#app', data: { vm: {}, isLoading : true }, created: function () { var self = this; let urlParams = new URLSearchParams(window.location.search); var countryName = urlParams.has('countryName') ? urlParams.get('countryName') : ''; var url = 'https://restcountries.eu/rest/v2/name/'+encodeURI(countryName)+'?fullText=true' $.get(url, function (data) { self.vm = data[0]; self.isLoading = false; }).fail(function() { document.write('No Data Display!!'); }); } });
|
小結
這次題目我前後大約花半天就把東西從無到有完成,個人覺得還算蠻順利的,但我寫的Front Code可能不太標準(因為我很少寫Js XDD)
如果有寫得不好的地方在歡迎指教
不得不說我覺得Vuejs寫起來真的蠻直覺,而且很多資源可以查閱學習來相對蠻容易的
相是Loading Page就有很多不同的樣式可以挑選.
__此文作者__:Daniel Shih(石頭)
__此文地址__: https://isdaniel.github.io/vue-first-Restcountries/
__版權聲明__:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!