串接 Restcountries By Vue.js

前文

最近面試有一間公司要求使用Restcountries API使用CRUD前端Html串接API,有看我文章的夥伴應該知道我大多是研究後端或CI/CD相關技術,對於前端技術較少研究,這次我打算使用vue.js來完成此次需求.

需求如下

  1. 分頁
  2. 顯示國家相關資訊
  3. 排序效果
  4. 點選國家名稱進入Detail頁面

因為以上幾點都是CRUD相關操作,關於CRUD相關操作使用三大框架就很適合(所以我選擇使用Vue)

話不多說先給大家看看成品 RestcountriesSample

Source Code

要使用的API介紹

雖然官網對於API介紹雖少,但我相信只要有常串API的人應該可以很快猜出每個API作用.

  • All:請求所有國家資訊
  • FULL NAME:查找國家By名子.

而且我發現大部分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 許可協議。轉載請註明出處!


如果本文對您幫助很大,可街口支付斗內鼓勵石頭^^