2025-03-06-天氣查詢應用程式」的第 2 步:畫面顯示三個城市的主要天氣資訊

2025-03-06-天氣查詢應用程式」的第 2 步:畫面顯示三個城市的主要天氣資訊

第 2 步:畫面顯示三個城市的主要天氣資訊


✅ 規格說明(第 2 步)

畫面要顯示三筆資料,每筆為一個城市,並顯示以下資訊:

  • 城市名稱 locationName
  • 天氣現象(Wx)→ 顯示今天天氣
  • 最高溫度(MaxT
  • 最低溫度(MinT
  • 降雨機率(PoP

每個城市一塊區塊,直向排列三排


✅ 完整範例程式碼(Vue 3 + Composition 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
49
50
51
52
<template>
<h2>🌦️ 三個城市的天氣概況</h2>

<div v-for="city in weatherData" :key="city.locationName" class="city-card">
<h3>{{ city.locationName }}</h3>
<p>🌤️ 天氣現象:{{ getWeatherElement(city, 'Wx') }}</p>
<p>🌡️ 最高溫度:{{ getWeatherElement(city, 'MaxT') }}°C</p>
<p>🥶 最低溫度:{{ getWeatherElement(city, 'MinT') }}°C</p>
<p>☔ 降雨機率:{{ getWeatherElement(city, 'PoP') }}%</p>
</div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const apiKey = '你的 API 金鑰'
const url = `https://opendata.cwa.gov.tw/api/v1/rest/datastore/F-C0032-001?Authorization=${apiKey}`

const allCities = ['臺北市', '臺中市', '高雄市']
const weatherData = ref([])

onMounted(async () => {
try {
const response = await fetch(url)
const data = await response.json()

const locations = data.records.location

weatherData.value = locations.filter(loc =>
allCities.includes(loc.locationName)
)
} catch (error) {
console.error('❌ 發生錯誤:', error)
}
})

// 取得指定欄位的第一筆預報值
function getWeatherElement(city, elementName) {
const element = city.weatherElement.find(el => el.elementName === elementName)
return element?.time[0]?.parameter?.parameterName || 'N/A'
}
</script>

<style scoped>
.city-card {
border: 1px solid #ccc;
padding: 1rem;
margin: 1rem 0;
border-radius: 0.5rem;
background: #f0f8ff;
}
</style>

🔍 說明重點

欄位 說明
Wx 天氣現象,如「晴時多雲」
PoP 降雨機率(百分比)
MaxT 最高溫度(攝氏)
MinT 最低溫度(攝氏)
.time[0] 代表第一個時間區段(通常是今晚~明晨)

✅ 下一步可選:

  • 💡 加上 <select> 選擇城市、只顯示單一城市資料
  • 💡 做出 RWD + 背景色變化
  • 💡 根據天氣現象改變 icon 或背景

你可以先跑跑看這個範例,再來決定是否繼續加入 RWD 或互動選單功能,我可以帶你一步步來 💪

好問題!你問的:

畫面並沒有直向排列,是不是因為沒有指定 border-box

其實不是關鍵問題在 border-box,而是:


✅ 【畫面沒直向排列】常見 3 個可能原因:


✅ 1. 最外層容器是否有 display: flex; flex-direction: column;

<style scoped> 裡應該這樣寫:

1
2
3
4
5
.weather-container {
display: flex;
flex-direction: column; /* ⬅️ 確保是垂直排列 */
gap: 1.5rem;
}

✅ 2. 確定 .weather-container 是否有套上 class?

你的 <template> 裡應該是:

1
2
3
4
5
<div class="weather-container">
<div v-for="city in weatherData" :key="city.locationName" class="city-card">
...
</div>
</div>

別漏掉 class="weather-container"
這是讓容器用 flex 垂直排列的關鍵。


✅ 3. 不是 border-box 問題(它是內容區域的計算方式)

  • box-sizing: border-box; 影響的是:padding + border 是否會被算進寬度
  • 跟「排列方向」沒關係,和 flex-direction 不同概念

🔧 快速檢查步驟:

  1. 檢查 weather-container 是否真的有 flex-direction: column
  2. 確保有套到 class
  3. 確保畫面寬度夠寬(手機版可能看不出差別)
  4. 開 DevTools → 點 .weather-container → 看 computed style 有沒有 display: flex

bonus:想強制直向排列

你可以加這行來幫助確認效果:

1
2
3
4
5
.weather-container {
display: flex;
flex-direction: column;
border: 2px dashed red; /* 測試用框線 */
}