0%

Vue 筆記 - 標籤對應資料實作

tab

這次縣市資料要使用這支 API 來實作,未來會延伸成氣象預報的表格。

使用 Bootstrap 標籤

使用 nav 這個功能讓標籤填滿頁面,預設要有六個選項:全部、北部、中部、南部、東部、外島。

所以就先把標籤建置好,

1
2
3
4
5
6
7
8
<nav class="nav nav-pills nav-fill">
<a class="nav-item nav-link active" href="#">全部</a>
<a class="nav-item nav-link" href="#">北部</a>
<a class="nav-item nav-link" href="#">中部</a>
<a class="nav-item nav-link" href="#">南部</a>
<a class="nav-item nav-link" href="#">東部</a>
<a class="nav-item nav-link" href="#">外島</a>
</nav>

並也改寫 Vue 筆記 - 表格中放入七天日期實作table 內容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="table-responsive">
<table class="table table-hover table-bordered">
<thead class="table-info sticky-top">
<tr>
<th scope="col">縣市</th>
// 加在這裡
<th scope="col">時間</th>
<th
scope="col"
v-for="(item, index) in dayList"
:key="index"
:class="{ holiday: item.holiday }"
>
<span>{{ item.date }}</span>
<br />
<span>{{ item.week }}</span>
</th>
</tr>
</thead>
</table>
</div>

加入縣市欄位

因為要在 table 顯示對應的縣市資料,原本時間是寫在 thead,現在要顯示在 tbody 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<tbody>
<tr>
<th>臺北市</th>
</tr>
<tr>
<th>新北市</th>
</tr>
<tr>
<th>臺中市</th>
</tr>
<tr>
<th>臺南市</th>
</tr>
</tbody>

得到畫面如下,並確認這是我要的呈現方式。

cities

使用 Vue.js 改寫

先確認有哪些需求:

  1. 要顯示台灣的城市。
  2. 因為要重複顯示,所以要使用迴圈。
  3. 因為要使用迴圈,所以會用到陣列。
  4. 要使用陣列把城市存起來。

tbody 改寫,

1
2
3
4
5
<tbody v-for="(item,index) in cities" :key="index">
<tr>
<th>{{ item.locationName }}</th>
</tr>
</tbody>

新增要使用的變數

  1. 因為這次要打天氣預報的 API,所以用 weatherItems 變數為空陣列存取取得的資料。
  2. 建立 cities 的陣列資料為空陣列,之後要把資料存到裡面。
  3. 建立 area 變數,因為縣市名基本上會變動機會不大,所以用五個陣列分別存好北區中區南區東區外島等縣市名稱。
  4. range 變數一開始設定為 -1,代表取得全部。
  5. active 是標籤目前狀態,點擊後為 true。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
data: {
weatherItems: [], //存放 api 資料的陣列
dayList: [],
cities: [],
area: [
["臺北市", "新北市", "桃園市", "基隆市"],
["臺中市", "新竹縣", "新竹市", "苗栗縣", "彰化縣", "南投縣"],
["臺南市", "高雄市", "雲林縣", "嘉義縣", "嘉義市", "屏東縣"],
["宜蘭縣", "花蓮縣", "臺東縣"],
["金門縣", "澎湖縣", "連江縣"],
],
range: -1,
active: false,
},

存取 API 的方法

  • 使用 axios 套件取得資料。
  • 執行 getData 方法。
1
2
3
4
5
6
7
getApi() {
axios.get(weather).then((res) => {
this.weatherItems = res.data.records.locations;
// console.log(this.weatherItems);
this.getData();
});
},

改寫標籤 HTML

把標籤部分加入 :class點擊事件

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
<nav class="nav nav-pills nav-fill">
<a
class="nav-item nav-link"
href="#"
:class="{active:range ==-1}"
@click.prevent="getArea(-1)"
>全部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 0}"
@click.prevent="getArea(0)"
>北部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 1}"
@click.prevent="getArea(1)"
>中部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 2}"
@click.prevent="getArea(2)"
>南部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 3}"
@click.prevent="getArea(3)"
>東部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 4}"
@click.prevent="getArea(4)"
>外島</a
>
</nav>

取得地區的方法

  • 在 HTML 有在方法中給予參數。
  • 把 range 變數的值改成參數值,以對應相對的縣市。
1
2
3
4
getArea(index) {
this.range = index;
this.getData();
},

取得資料方法

  • 時間部份可以參考這篇

取得城市

  • 首先一樣清空 cities 陣列,以確保不會重複傳值。
  • 因資料結構較冗長,把取得的資料存在一個 locations 的變數中。
  • 另外給予一個 location2 的空陣列,要來存篩選後的結果。
  • 判斷如果 range 不是 -1 的時候要做哪些事情。
    1. assignArea 變數存 area 的陣列要對應 range 所選到的值。
    2. location2locations 資料篩選後的結果。
    3. assignArea 的值比對資料中的地區名稱,因為資料陣列是從 0 開始,所以設定 >=0 就會確保一定找得到。
    4. 否則就是全部都顯示。
  • 在把篩選後的結果(location2)所迴圈並依序把地區名稱存回 cities 的空陣列中。
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
getData() {
this.dayList = []; //存放日期的陣列
for (let i = 0; i < 7; i++) {
let day = moment().add(i, "days");
let week = Number(day.format("E"));
this.dayList.push({
date: day.format("MM/DD"),
d: day.format("YYYY-MM-DD"), //驗證用
week: this.toWeek(Number(week)),
holiday: week === 6 || week === 7,
});
}
//取城市
this.cities = [];
let locations = this.weatherItems[0].location;
let location2 = [];
//縣市標籤
if (this.range != -1) {
let assignArea = this.area[this.range];
location2 = locations.filter((element) =>
assignArea.indexOf(element.locationName) >= 0
);
} else {
location2 = locations;
}

location2.forEach(item => {
this.cities.push({
locationName: item.locationName
})
})
},

完整程式碼

HTML

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<div id="app">
<div class="container-fluid">
<!-- nav -->
<section>
<nav class="nav nav-pills nav-fill">
<a
class="nav-item nav-link"
href="#"
:class="{active:range ==-1}"
@click.prevent="getArea(-1)"
>全部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 0}"
@click.prevent="getArea(0)"
>北部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 1}"
@click.prevent="getArea(1)"
>中部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 2}"
@click.prevent="getArea(2)"
>南部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 3}"
@click.prevent="getArea(3)"
>東部</a
>
<a
class="nav-item nav-link"
href="#"
:class="{active:range == 4}"
@click.prevent="getArea(4)"
>外島</a
>
</nav>
</section>

<!-- table -->
<section>
<div class="table-responsive">
<table class="table table-hover table-bordered">
<thead class="table-info sticky-top">
<tr>
<th scope="col">縣市</th>
<th scope="col">時間</th>
<th
scope="col"
v-for="(item, index) in dayList"
:key="index"
:class="{ holiday: item.holiday }"
>
<span>{{ item.date }}</span>
<br />
<span>{{ item.week }}</span>
</th>
</tr>
</thead>
<tbody v-for="(item,index) in cities" :key="index">
<tr>
<th>{{ item.locationName }}</th>
</tr>
</tbody>
</table>
</div>
</section>
</div>
</div>

Vue

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
let vm = new Vue({
el: "#app",
data: {
weatherItems: [],
dayList: [],
cities: [],
area: [
["臺北市", "新北市", "桃園市", "基隆市"],
["臺中市", "新竹縣", "新竹市", "苗栗縣", "彰化縣", "南投縣"],
["臺南市", "高雄市", "雲林縣", "嘉義縣", "嘉義市", "屏東縣"],
["宜蘭縣", "花蓮縣", "臺東縣"],
["金門縣", "澎湖縣", "連江縣"],
],
range: -1,
active: false,
},
created() {
this.getApi();
},
methods: {
getApi() {
axios.get(weather).then((res) => {
this.weatherItems = res.data.records.locations;
// console.log(this.weatherItems);
this.getData();
});
},
getArea(index) {
this.range = index;
this.getData();
},
getData() {
this.dayList = []; //存放日期的陣列
for (let i = 0; i < 7; i++) {
let day = moment().add(i, "days");
let week = Number(day.format("E"));
this.dayList.push({
date: day.format("MM/DD"),
d: day.format("YYYY-MM-DD"), //驗證用
week: this.toWeek(Number(week)),
holiday: week === 6 || week === 7,
});
}
//取城市
this.cities = [];
let locations = this.weatherItems[0].location;
let location2 = [];
//縣市標籤
if (this.range != -1) {
let assignArea = this.area[this.range];
location2 = locations.filter(
(element) => assignArea.indexOf(element.locationName) >= 0
);
} else {
location2 = locations;
}

location2.forEach((item) => {
this.cities.push({
locationName: item.locationName,
});
});
},
toWeek(week) {
switch (week) {
case 1:
return "星期一";
case 2:
return "星期二";
case 3:
return "星期三";
case 4:
return "星期四";
case 5:
return "星期五";
case 6:
return "星期六";
case 7:
return "星期日";
default:
return "";
}
},
},
});

Demo