0%

Vue 筆記 - 台灣空氣品質列表實作

mask

最近空氣品質有點糟糕,有鼻子過敏的我有點受不了,想說做個簡易版讓自己要去該地區可以查一下該地空氣品質如何的小功能。

確認需求

  1. 我需要一個 input 當作搜尋列表。
  2. 要呈現全台縣市、行政區、空氣品質與日期,等四個資訊。
  3. 需要有 RWD,電腦版為四排,平板有兩排,手機為單列。

架構先寫好

照慣例就先把基本的版型切好,然後放入假資料或是預計要呈現的欄位。

HTML

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">
<div class="header">
<div class="container">
<div class="input-group">
<h1>台灣空氣品質列表</h1>
<input
type="search"
v-model.trim="input"
placeholder="搜尋要找的縣市,例:新北市"
/>
</div>
</div>
</div>

<div class="container">
<ul class="list" v-for="(item, index) in typeMenu" :key="index">
<li class="county">{{item.County}}</li>
<li class="siteName">行政區:{{item.SiteName}}</li>
<li class="airStatus">空氣品質: {{item.Status}}</li>
<li class="publishTime">{{item.PublishTime}}</li>
</ul>
</div>
</div>

SCSS

我有先做一個 RWD 的 SCSS 元件,所以就直接 import 進來,就不用一直寫 media query 這冗長的語法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@mixin pc {
@media (max-width: 1024px) {
@content;
}
}

@mixin pad {
@media (max-width: 768px) {
@content;
}
}

@mixin phone {
@media (max-width: 414px) {
@content;
}
}

SCSS 樣式

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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
@import "_media";

* {
padding: 0;
margin: 0;
list-style: none;
}

body {
box-sizing: border-box;
background-color: #eee;
}

.container {
width: 1024px;
margin: 0 auto;
display: flex;
justify-content: center;
flex-wrap: wrap;
padding: 20px 0;
@include pad {
width: 100%;
}

@include phone {
width: 100%;
}
}

.header {
background-image: url("https://images.unsplash.com/photo-1493364391862-bb90969a4cc1?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80");
background-position: center center;
background-size: cover;
}

@include pad {
width: 100%;
}

@include phone {
width: 100%;
}
.input-group {
margin: 3% 0;
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
@include pad {
display: block;
text-align: center;
}
h1 {
color: #0d47a1;
margin-right: 1%;
text-shadow: #333;
@include pad {
margin-right: 0;
margin-bottom: 3%;
}
}
> input {
width: 70%;
padding: 10px 15px;
border: 1px solid #fff;
font-size: 18px;
outline: none;
}
}

.list {
width: 21%;
padding: 1%;
margin: 1% 1%;
box-shadow: 0 0 5px 2px #ddd;
background-color: #ffffff;
border-radius: 6px;
@include pad {
width: 43%;
text-align: center;
}
@include phone {
width: 98%;
text-align: center;
}
> li {
padding-bottom: 5%;
cursor: pointer;
}
&:hover {
background-color: #e0f7fa;
transition: all 1s;
}
.county {
font-size: 24px;
color: #1e88e5;
font-weight: bold;
}
.siteName {
font-size: 18px;
font-weight: bold;
}
}

.footer {
background-color: #1e88e5;
line-height: 70px;

.text,
p {
color: #fff;
}
}

Vue.js

使用的 api 是這個

說明:

  1. 先宣告一個空陣列 cantacts 來裝 api 資料。
  2. 預設讓 input 為空值,如果要先預設值也可以先寫在裡面。
  3. 在 DOM 生成前載入資料,所以使用 create() 方法。
  4. 自訂一個 typeMenu 函式,要實作篩選功能。
  5. 我要篩選出跟輸入框一樣的關鍵字,判斷如果 input 有跟資料一樣的關鍵字,就回傳陣列資料中是跟輸入框當中相同的文字。
  6. 如果輸入框沒有文字,就顯示所有資料。

    indexOf() !==-1 是指要找得到文字,找不到就是 -1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let vm = new Vue({
el: "#app",
data: {
contacts: [],
input: "",
},
created() {
axios.get(aqi).then((res) => {
this.contacts = res.data.records;
});
},
computed: {
typeMenu() {
if (this.input) {
return this.contacts.filter((item) => {
return item.County.toLowerCase().indexOf(this.input.toLowerCase()) !== -1;
});
} else {
return this.contacts;
}
},
},
});

寫到這邊有確認功能可以實作了,但程式碼有點不好閱讀,所以就來優化一下,把城市名稱關鍵字這兩段各用一個變數存取。

1
2
let keyword = this.input.toLowerCase();
let countyName = item.County.toLowerCase();

所以這一段優化後就會變成,

1
2
3
4
5
6
7
8
9
10
11
typeMenu() {
if (this.input) {
return this.contacts.filter((item) => {
let keyword = this.input.toLowerCase();
let countyName = item.County.toLowerCase();
return countyName.indexOf(keyword) !== -1;
});
} else {
return this.contacts;
}
},

Demo: https://hsuchihting.github.io/air_quality/index.html

參考資料

開胃餐點 - 清爽表單處理佐雙向資料